Files
test/sf_tool_management/models/base.py

1048 lines
61 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import re
import logging
from datetime import timedelta
from odoo import SUPERUSER_ID
from odoo import fields, models, api
from odoo.exceptions import ValidationError
class MachineTableToolChangingApply(models.Model):
_name = 'sf.machine.table.tool.changing.apply'
_description = '机床换刀申请'
_order = 'cutter_spacing_code_id'
name = fields.Char('名称', related='maintenance_equipment_id.name', store=True)
# 设备信息
maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='CNC机床', readonly=True,
domain=[('category_id.equipment_type', '=', '机床')])
production_line_id = fields.Many2one('sf.production.line', string='生产线', readonly=True)
machine_table_type_id = fields.Many2one('maintenance.equipment.category', string='机床类型', readonly=True,
compute='_compute_machine_table_type_id')
machine_tool_code = fields.Char(string='机台号', related='maintenance_equipment_id.name')
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', readonly=True,
required=True, domain="[('equipment_id', '=', maintenance_equipment_id)]")
# 功能刀具信息
code = fields.Char('编码', related='functional_tool_name_id.code')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
functional_tool_name = fields.Char(string='刀具名称', related='functional_tool_name_id.name', store=True)
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', store=True,
domain=[('product_id.name', '=', '功能刀具')],
related='functional_tool_name_id.barcode_id')
rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid')
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', domain=[('assemble_status', '=', '1')],
string='功能刀具名称')
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
related='functional_tool_name_id.after_assembly_functional_tool_type_id')
tool_position_interface_type = fields.Selection(
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
('直装固定式', '直装固定式')], string='刀位接口型号')
diameter = fields.Float(string='刀具直径(mm)')
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
max_lifetime_value = fields.Integer(string='最大寿命值(min)')
alarm_value = fields.Integer(string='报警值(min)')
used_value = fields.Integer(string='已使用值(min)')
whether_standard_knife = fields.Boolean(string='是否标准刀', default=True)
extension_length = fields.Float(string='伸出长(mm)')
effective_length = fields.Float(string='有效长(mm)')
functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警')], string='功能刀具状态', store=True,
default='正常', compute='_compute_functional_tool_status')
assembly_order_code = fields.Char(string='组装单编码', readonly=True)
applicant = fields.Char(string='申请人', readonly=True)
reason_for_applying = fields.Char(string='申请原因', readonly=True)
remark = fields.Char(string='备注说明', readonly=False)
status = fields.Selection([('0', '未操作'), ('1', '已申请换刀'), ('2', '已转移'), ('3', '已组装')],
string='操作状态', default='0')
sf_functional_tool_assembly_id = fields.Many2one('sf.functional.tool.assembly', '功能刀具组装单', readonly=True)
active = fields.Boolean(string='已归档', default=True)
@api.depends('alarm_value', 'used_value')
def _compute_functional_tool_status(self):
for record in self:
if record.alarm_value < record.used_value:
record.sudo().functional_tool_status = '报警'
else:
record.sudo().functional_tool_status = '正常'
@api.depends('maintenance_equipment_id')
def _compute_machine_table_type_id(self):
for record in self:
if record:
record.sudo().production_line_id = record.maintenance_equipment_id.production_line_id.id
record.sudo().machine_table_type_id = record.maintenance_equipment_id.category_id.id
record.sudo().machine_tool_code = record.maintenance_equipment_id.code
else:
record.sudo().production_line_id = None
record.sudo().machine_table_type_id = None
record.sudo().machine_tool_code = None
@api.constrains("cutter_spacing_code_id")
def _check_cutter_spacing_code_id(self):
for obj in self:
records = self.env['sf.machine.table.tool.changing.apply'].search([
('maintenance_equipment_id', '=', obj.maintenance_equipment_id.id),
('cutter_spacing_code_id', '=', obj.cutter_spacing_code_id.id)])
if len(records) > 1:
raise ValidationError('该刀位号已存在,请重新选择!!!')
@api.constrains('functional_tool_status')
def automation_apply_for_tool_change(self):
"""
自动申请换刀
:return:
"""
# 更新数据到机台换刀申请界面
if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id:
machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search(
[('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id)
])
# 创建功能刀具预警记录
self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self})
# 新建组装任务
sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({
'functional_tool_name': self.functional_tool_name,
'functional_tool_type_id': self.functional_tool_type_id.id,
'functional_tool_diameter': self.diameter,
'knife_tip_r_angle': self.knife_tip_r_angle,
'coarse_middle_thin': '3',
'new_former': '0',
'functional_tool_length': self.extension_length,
'effective_length': self.effective_length,
'loading_task_source': '1',
'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
'production_line_name_id': self.production_line_id.id,
'machine_tool_name_id': self.maintenance_equipment_id.id,
'applicant': '系统自动',
'apply_time': fields.Datetime.now(),
'cutter_spacing_code_id': self.cutter_spacing_code_id.id,
'whether_standard_knife': self.whether_standard_knife,
'reason_for_applying': '机台报警自动换刀',
'sf_machine_table_tool_changing_apply_id': self.id
})
machine_table_tool_changing_apply.write(
{'status': '1',
'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id})
def revocation_1(self):
"""
换刀申请撤回按键
:return:
"""
# 撤回功能刀具组装创建的任务
self.env['sf.functional.tool.assembly'].search(
[('id', '=', self.sf_functional_tool_assembly_id.id),
('loading_task_source', '=', '1')]).unlink()
# 撤回数据更新
self.env['sf.machine.table.tool.changing.apply'].search(
[('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id)]).write(
{'status': '0',
'sf_functional_tool_assembly_id': None
})
def revocation_2(self):
"""
转移撤回按键
:return:
"""
self.env['sf.machine.table.tool.changing.apply'].search(
[('name', '=', self.name.id)]).write({'status': '0'})
def create_tool_change_application(self):
"""
根据已有机床刀位创建机台换刀申请记录
"""
maintenance_equipment_ids = self.env['maintenance.equipment'].sudo().search(
[('product_template_ids', '!=', False)])
tool_changing_apply = self.env['sf.machine.table.tool.changing.apply']
if maintenance_equipment_ids:
for maintenance_equipment_id in maintenance_equipment_ids:
if maintenance_equipment_id.product_template_ids:
for product_template_id in maintenance_equipment_id.product_template_ids:
tool_changing_apply.sudo().create({
'maintenance_equipment_id': product_template_id.equipment_id.id,
'cutter_spacing_code_id': product_template_id.id
})
class CAMWorkOrderProgramKnifePlan(models.Model):
_name = 'sf.cam.work.order.program.knife.plan'
_inherit = ['mail.thread']
_description = 'CAM工单程序用刀计划'
name = fields.Char('工单任务编号')
cam_procedure_code = fields.Char('程序名')
filename = fields.Char('文件')
cam_cutter_spacing_code = fields.Char('刀号')
tool_position_interface_type = fields.Selection(
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
('直装固定式', '直装固定式')], string='刀位接口型号')
production_line_id = fields.Many2one('sf.production.line', string='生产线', group_expand='_read_group_names')
machine_table_name_id = fields.Many2one('maintenance.equipment', string='机床名称',
domain="[('production_line_id', '=', production_line_id)]")
machine_table_name = fields.Char(string='机台号', readonly=True, related='machine_table_name_id.name')
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号',
domain="[('equipment_id', '=', machine_table_name_id)]")
whether_standard_knife = fields.Boolean(string='是否标准刀', default=True)
need_knife_time = fields.Datetime(string='用刀时间', readonly=False)
applicant = fields.Char(string='申请人', readonly=True)
applicant_time = fields.Datetime(string='申请时间', readonly=True)
reason_for_applying = fields.Char(string='申请原因', readonly=False)
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号',
domain=[('product_id.name', '=', '功能刀具')])
functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
compute='_compute_tool_number', store=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_tool_number', store=True)
diameter = fields.Float(string='刀具直径(mm)', compute='_compute_tool_number', store=True)
tool_included_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_tool_number', store=True)
tool_loading_length = fields.Float(string='总长度(mm)', compute='_compute_tool_number', store=True)
extension_length = fields.Float(string='伸出长(mm)')
effective_length = fields.Float(string='有效长(mm)')
new_former = fields.Selection([('0', ''), ('1', '')], string='新/旧', readonly=False, default='0')
coarse_middle_thin = fields.Selection([("1", ""), ('2', ''), ('3', '')], default='3',
string='粗/中/精', readonly=False)
L_D = fields.Float(string='L/D值', readonly=False)
clearance_length = fields.Float(string='避空长(mm)', compute='_compute_tool_number', store=True)
required_cutting_time = fields.Integer(string='需切削时长', readonly=False)
process_type = fields.Char('加工类型')
margin_x_y = fields.Float('余量_X/Y')
margin_z = fields.Float('余量_Z')
finish_depth = fields.Float('加工深度')
shank_model = fields.Char('刀柄型号')
estimated_processing_time = fields.Char('预计加工时间')
plan_execute_status = fields.Selection([('0', '待下发'), ('1', '执行中'), ('2', '已完成')],
string='计划执行状态', default='0', readonly=False, tracking=True)
sf_functional_tool_assembly_id = fields.Many2one('sf.functional.tool.assembly', '功能刀具组装', readonly=True)
active = fields.Boolean(string='已归档', default=True)
@api.depends('functional_tool_name')
def _compute_tool_number(self):
for item in self:
inventory = self.env['sf.tool.inventory'].sudo().search([('name', '=', item.functional_tool_name)])
if inventory:
item.functional_tool_type_id = inventory.functional_cutting_tool_model_id.id
item.tool_groups_id = inventory.tool_groups_id.id
item.diameter = int(inventory.diameter)
item.tool_included_angle = inventory.angle
item.tool_loading_length = inventory.tool_length
item.clearance_length = inventory.blade_length
else:
item.functional_tool_type_id = False
item.tool_groups_id = False
item.diameter = 0
item.tool_included_angle = 0
item.tool_loading_length = 0
item.clearance_length = 0
@api.model
def _read_group_names(self, categories, domain, order):
names = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(names)
def apply_for_tooling(self):
"""
申请装刀
:return:
"""
record = self.env['sf.functional.tool.assembly'].create({
'functional_tool_name': self.functional_tool_name,
'functional_tool_type_id': self.functional_tool_type_id.id,
'tool_groups_id': self.tool_groups_id.id,
'functional_tool_diameter': self.diameter,
'knife_tip_r_angle': self.tool_included_angle,
'tool_loading_length': self.tool_loading_length,
'functional_tool_length': self.extension_length,
'effective_length': self.effective_length,
'whether_standard_knife': self.whether_standard_knife,
'coarse_middle_thin': self.coarse_middle_thin,
'new_former': self.new_former,
'production_line_name_id': self.production_line_id.id,
'machine_tool_name_id': self.machine_table_name_id.id,
'cutter_spacing_code_id': self.env['maintenance.equipment.tool'].sudo().search(
[('code', '=', self.cam_cutter_spacing_code), ('equipment_id', '=', self.machine_table_name_id.id)]).id,
'loading_task_source': '0',
'applicant': self.env.user.name,
'use_tool_time': fields.Datetime.now() + timedelta(
hours=4) if not self.need_knife_time else self.need_knife_time,
'reason_for_applying': '工单用刀',
'sf_cam_work_order_program_knife_plan_id': self.id
})
self.sf_functional_tool_assembly_id = record.id
# 将计划执行状态改为执行中
self.env['sf.cam.work.order.program.knife.plan'].search(
[('name', '=', self.name), ('functional_tool_name', '=', self.functional_tool_name)]).write(
{'plan_execute_status': '1',
'applicant': self.env.user.name})
def revocation(self):
"""
撤回装刀申请
:return:
"""
self.env['sf.functional.tool.assembly'].sudo().search(
[('assembly_order_code', '=', self.sf_functional_tool_assembly_id.assembly_order_code),
('loading_task_source', '=', '0')]).unlink()
# 将计划执行状态改为待执行,同时清除申请人、功能刀具组装字段数据
self.env['sf.cam.work.order.program.knife.plan'].search(
[('name', '=', self.name), ('functional_tool_name', '=', self.functional_tool_name)]).write(
{'plan_execute_status': '0',
'applicant': None,
'sf_functional_tool_assembly_id': None})
def create_cam_work_plan(self, cnc_processing_ids):
"""
根据传入的工单信息查询是否有需要的功能刀具如果没有则生成CAM工单程序用刀计划
"""
for cnc_processing in cnc_processing_ids:
status = False
if cnc_processing.cutting_tool_name:
functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search(
[('name', '=', cnc_processing.cutting_tool_name)])
if functional_tools:
for functional_tool in functional_tools:
if functional_tool.on_tool_stock_num == 0:
if functional_tool.tool_stock_num == 0 and functional_tool.side_shelf_num == 0:
status = True
else:
status = True
if status:
knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
'name': cnc_processing.workorder_id.production_id.name,
'cam_procedure_code': cnc_processing.program_name,
'filename': cnc_processing.cnc_id.name,
'functional_tool_name': cnc_processing.cutting_tool_name,
'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
'process_type': cnc_processing.processing_type,
'margin_x_y': float(cnc_processing.margin_x_y),
'margin_z': float(cnc_processing.margin_z),
'finish_depth': float(cnc_processing.depth_of_processing_z),
'extension_length': float(cnc_processing.cutting_tool_extension_length),
'shank_model': cnc_processing.cutting_tool_handle_type,
'estimated_processing_time': cnc_processing.estimated_processing_time,
})
logging.info('CAM工单程序用刀计划创建成功')
# 创建装刀请求
knife_plan.apply_for_tooling()
else:
logging.info('功能刀具【%s】满足CNC用刀需求' % cnc_processing.cutting_tool_name)
def unlink_cam_plan(self, production):
for item in production:
cam_plan_ids = self.env['sf.cam.work.order.program.knife.plan'].search([('name', '=', item.name)])
for cam_plan_id in cam_plan_ids:
assembly_id = cam_plan_id.sf_functional_tool_assembly_id
if assembly_id.assemble_status in ('0', '待组装') and not assembly_id.start_preset_bool:
logging.info('%s删除成功!!!' % assembly_id)
assembly_id.sudo().unlink()
logging.info('unlink_cam_plan成功')
cam_plan_ids.sudo().unlink()
class FunctionalToolAssembly(models.Model):
_name = 'sf.functional.tool.assembly'
_inherit = ['mail.thread']
_description = '功能刀具组装'
_order = 'assemble_status, use_tool_time asc'
@api.depends('functional_tool_name')
def _compute_name(self):
for obj in self:
obj.name = obj.assembly_order_code
code = fields.Char('功能刀具编码', readonly=True)
rfid = fields.Char('Rfid', readonly=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=True)
name = fields.Char(string='名称', readonly=True, compute='_compute_name')
assembly_order_code = fields.Char(string='组装单编码', readonly=True)
functional_tool_name_id = fields.Many2one('product.product', string='功能刀具', readonly=True)
functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
group_expand='_read_group_functional_tool_type_ids')
functional_tool_diameter = fields.Float(string='功能刀具直径(mm)', readonly=True)
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
coarse_middle_thin = fields.Selection([("1", ""), ('2', ''), ('3', '')], string='粗/中/精', readonly=True)
new_former = fields.Selection([('0', ''), ('1', '')], string='新/旧', readonly=True)
tool_loading_length = fields.Float(string='总长度(mm)', readonly=True)
functional_tool_length = fields.Float(string='伸出长(mm)', readonly=True)
effective_length = fields.Float(string='有效长(mm)', readonly=True)
loading_task_source = fields.Selection([('0', 'CAM装刀'), ('1', '机台换刀'), ('2', '按库存组装')],
string='装刀任务来源', readonly=True)
use_tool_time = fields.Datetime(string='用刀时间', readonly=True)
production_line_name_id = fields.Many2one('sf.production.line', string='申请产线', readonly=True)
machine_tool_name_id = fields.Many2one('maintenance.equipment', string='申请机台', readonly=True)
machine_tool_code = fields.Char(string='机台号', readonly=True)
applicant = fields.Char(string='申请人', readonly=True)
apply_time = fields.Datetime(string='申请时间', default=fields.Datetime.now(), readonly=True)
assemble_status = fields.Selection([('0', '待组装'), ('1', '已组装')], string='组装状态', default='0',
tracking=True, readonly=True)
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', readonly=True)
whether_standard_knife = fields.Boolean(string='是否标准刀', default=True, readonly=True)
reason_for_applying = fields.Char(string='申请原因', readonly=True)
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
alarm_value = fields.Integer(string='报警值(min)', readonly=True)
used_value = fields.Integer(string='已使用值(min)', readonly=True)
image = fields.Binary('图片', readonly=True)
@api.model
def _read_group_functional_tool_type_ids(self, categories, domain, order):
"""读取分组自定义以便在看板视图中显示所有的类别,即使它们为空"""
functional_tool_type_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(functional_tool_type_ids)
# 刀具物料信息
# ==============整体式刀具型号=============
integral_freight_barcode_id = fields.Many2one('sf.shelf.location', string='整体式刀具货位')
integral_lot_id = fields.Many2one('stock.lot', string='整体式刀具批次')
integral_product_id = fields.Many2one('product.product', string='整体式刀具名称',
compute='_compute_integral_product_id', store=True)
cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号',
related='integral_product_id.cutting_tool_model_id')
integral_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='整体式刀具规格',
related='integral_product_id.specification_id')
sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌',
related='integral_product_id.brand_id')
@api.depends('integral_lot_id')
def _compute_integral_product_id(self):
for item in self:
if item.integral_lot_id:
item.integral_product_id = item.integral_lot_id.product_id.id
# =================刀片型号=============
blade_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀片货位')
blade_lot_id = fields.Many2one('stock.lot', string='刀片批次')
blade_product_id = fields.Many2one('product.product', string='刀片名称', compute='_compute_blade_product_id',
store=True)
cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号',
related='blade_product_id.cutting_tool_model_id')
blade_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀片规格',
related='blade_product_id.specification_id')
sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', related='blade_product_id.brand_id')
@api.depends('blade_lot_id')
def _compute_blade_product_id(self):
for item in self:
if item.blade_lot_id:
item.blade_product_id = item.blade_lot_id.product_id.id
# ==============刀杆型号================
bar_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀杆货位')
bar_lot_id = fields.Many2one('stock.lot', string='刀杆批次')
bar_product_id = fields.Many2one('product.product', string='刀杆名称', compute='_compute_bar_product_id',
store=True)
cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号',
related='bar_product_id.cutting_tool_model_id')
bar_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀杆规格',
related='bar_product_id.specification_id')
sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', related='bar_product_id.brand_id')
@api.depends('bar_lot_id')
def _compute_bar_product_id(self):
for item in self:
if item.bar_lot_id:
item.bar_product_id = item.bar_lot_id.product_id.id
# =============刀盘型号================
pad_freight_barcode_id = fields.Many2one('sf.shelf.location', string='刀盘货位')
pad_lot_id = fields.Many2one('stock.lot', string='刀盘批次')
pad_product_id = fields.Many2one('product.product', string='刀盘名称', compute='_compute_pad_product_id',
store=True)
cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号',
related='pad_product_id.cutting_tool_model_id')
pad_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀盘规格',
related='pad_product_id.specification_id')
sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', related='pad_product_id.brand_id')
@api.depends('pad_lot_id')
def _compute_pad_product_id(self):
for item in self:
if item.pad_lot_id:
item.pad_product_id = item.pad_lot_id.product_id.id
# ==============刀柄型号==============
handle_freight_rfid = fields.Char('刀柄Rfid', compute='_compute_handle_product_id', store=True)
handle_code_id = fields.Many2one('stock.lot', '刀柄序列号')
handle_product_id = fields.Many2one('product.product', string='刀柄名称', compute='_compute_handle_product_id',
store=True)
cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号',
related='handle_product_id.cutting_tool_model_id')
handle_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀柄规格',
related='handle_product_id.specification_id')
sf_tool_brand_id_5 = fields.Many2one('sf.machine.brand', '刀柄品牌', related='handle_product_id.brand_id')
@api.depends('handle_code_id')
def _compute_handle_product_id(self):
for item in self:
if item.handle_code_id:
item.handle_product_id = item.handle_code_id.product_id.id
item.handle_freight_rfid = item.handle_code_id.rfid
else:
item.handle_product_id = False
item.handle_freight_rfid = False
# ==============夹头型号==============
chuck_freight_barcode_id = fields.Many2one('sf.shelf.location', string='夹头货位')
chuck_lot_id = fields.Many2one('stock.lot', string='夹头批次')
chuck_product_id = fields.Many2one('product.product', string='夹头名称', compute='_compute_chuck_product_id',
store=True)
cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号',
related='chuck_product_id.cutting_tool_model_id')
chuck_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='夹头规格',
related='chuck_product_id.specification_id')
sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', related='chuck_product_id.brand_id')
@api.depends('chuck_lot_id')
def _compute_chuck_product_id(self):
for item in self:
if item.chuck_lot_id:
item.chuck_product_id = item.chuck_lot_id.product_id.id
# ==================待删除字段==================
integral_freight_barcode = fields.Char('整体式刀具货位')
blade_freight_barcode = fields.Char('刀片货位')
bar_freight_barcode = fields.Char('刀杆货位')
pad_freight_barcode = fields.Char('刀盘货位')
chuck_freight_barcode = fields.Char('夹头货位')
blade_name = fields.Char('')
integral_name = fields.Char('')
blade_code_id = fields.Many2one('stock.lot', '刀片序列号')
integral_code_id = fields.Many2one('stock.lot', '整体式刀具序列号')
bar_code_id = fields.Many2one('stock.lot', '刀杆序列号')
bar_name = fields.Char('')
pad_code_id = fields.Many2one('stock.lot', '刀盘序列号')
pad_name = fields.Char('')
handle_name = fields.Char('')
chuck_code_id = fields.Many2one('stock.lot', '夹头序列号')
chuck_name = fields.Char('')
# ==============================================
# 组装功能刀具参数信息
start_preset_bool = fields.Boolean('开始预调', default=False)
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True)
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', readonly=True)
after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model',
string='组装后功能刀具类型', readonly=True)
after_assembly_functional_tool_diameter = fields.Float(string='组装后功能刀具直径(mm)', readonly=True,
digits=(10, 3))
after_assembly_knife_tip_r_angle = fields.Float(string='组装后刀尖R角(mm)', readonly=True, digits=(10, 3))
after_assembly_new_former = fields.Selection([('0', ''), ('1', '')], string='组装后新/旧', readonly=True)
cut_time = fields.Integer(string='已切削时间(min)', readonly=True)
cut_length = fields.Float(string='已切削长度(mm)', readonly=True)
cut_number = fields.Integer(string='已切削次数', readonly=True)
after_assembly_whether_standard_knife = fields.Boolean(string='组装后是否标准刀', default=True, readonly=True)
after_assembly_coarse_middle_thin = fields.Selection([("1", ""), ('2', ''), ('3', '')],
string='组装后粗/中/精', readonly=True)
after_assembly_max_lifetime_value = fields.Integer(string='组装后最大寿命值(min)', readonly=True)
after_assembly_alarm_value = fields.Integer(string='组装后报警值(min)', readonly=True)
after_assembly_used_value = fields.Integer(string='组装后已使用值(min)', readonly=True)
after_assembly_tool_loading_length = fields.Float(string='组装后总长度(mm)', readonly=True, digits=(10, 3))
after_assembly_handle_length = fields.Float(string='组装后刀柄长度(mm)', readonly=True, digits=(10, 3))
after_assembly_functional_tool_length = fields.Float(string='组装后伸出长(mm)', readonly=True, digits=(10, 3))
after_assembly_effective_length = fields.Float(string='组装后有效长(mm)', readonly=True)
L_D_number = fields.Float(string='L/D值(mm)', readonly=True)
hiding_length = fields.Float(string='避空长(mm)', readonly=True)
# functional_tool_cutting_type = fields.Char(string='功能刀具切削类型', readonly=False)
tool_loading_person = fields.Char(string='装刀人', readonly=True)
tool_loading_time = fields.Datetime(string='装刀时间', readonly=True)
remark = fields.Char(string='备注说明', readonly=True)
check_box_1 = fields.Boolean(string='复选框', default=False, readonly=False)
sf_machine_table_tool_changing_apply_id = fields.Many2one('sf.machine.table.tool.changing.apply', '机床换刀申请',
readonly=True)
sf_cam_work_order_program_knife_plan_id = fields.Many2one('sf.cam.work.order.program.knife.plan',
'CAM工单程序用刀计划', readonly=True, )
active = fields.Boolean(string='已归档', default=True)
def action_open_reference1(self):
self.ensure_one()
return {
'res_model': self._name,
'type': 'ir.actions.act_window',
'views': [[False, "form"]],
'res_id': self.id,
}
def put_start_preset(self):
self.search([('start_preset_bool', '=', True)]).write({'start_preset_bool': False})
self.write({
'after_assembly_tool_loading_length': 0,
'after_assembly_functional_tool_diameter': 0,
'after_assembly_knife_tip_r_angle': 0,
'start_preset_bool': True
})
return {
'type': 'ir.actions.act_window',
'res_model': 'sf.functional.tool.assembly.order',
'name': '功能刀具组装单',
'view_mode': 'form',
'target': 'new',
'context': {'default_name': self.name,
'default_assembly_order_code': self.assembly_order_code,
'default_production_line_name_id': self.production_line_name_id.id,
'default_machine_tool_name_id': self.machine_tool_name_id.id,
'default_cutter_spacing_code_id': self.cutter_spacing_code_id.id,
'default_functional_tool_name': self.functional_tool_name,
'default_functional_tool_type_id': self.functional_tool_type_id.id,
'default_tool_groups_id': self.tool_groups_id.id,
'default_functional_tool_diameter': self.functional_tool_diameter,
'default_knife_tip_r_angle': self.knife_tip_r_angle,
'default_tool_loading_length': self.tool_loading_length,
'default_functional_tool_length': self.functional_tool_length,
'default_effective_length': self.effective_length,
'default_whether_standard_knife': self.whether_standard_knife,
'default_coarse_middle_thin': self.coarse_middle_thin,
'default_new_former': self.new_former,
'default_use_tool_time': self.use_tool_time,
'default_reason_for_applying': self.reason_for_applying
}
}
def _get_code(self, loading_task_source):
"""
自动生成组装单编码
"""
new_time = str(fields.Date.today())
datetime = new_time[2:4] + new_time[5:7]
if loading_task_source == '0':
code = 'C' + datetime
elif loading_task_source == '1':
code = 'J' + datetime
elif loading_task_source == '2':
code = 'K' + datetime
else:
code = False
functional_tool_assembly = self.env['sf.functional.tool.assembly'].sudo().search(
[('loading_task_source', '=', loading_task_source),
('assembly_order_code', 'ilike', code)], limit=1, order="id desc")
if not functional_tool_assembly:
num = "%03d" % 1
else:
m = int(functional_tool_assembly.assembly_order_code[-3:]) + 1
num = "%03d" % m
return code + str(num)
def get_functional_tool(self, val):
functional_tools = self.env['sf.functional.tool.assembly'].search(
[('after_assembly_functional_tool_name', '=', val.get('after_assembly_functional_tool_name')),
('after_assembly_functional_tool_diameter', '=', val.get('after_assembly_functional_tool_diameter')),
('after_assembly_knife_tip_r_angle', '=', val.get('after_assembly_knife_tip_r_angle')),
('after_assembly_coarse_middle_thin', '=', val.get('after_assembly_coarse_middle_thin'))])
for functional_tool in functional_tools:
if functional_tool.barcode_id.quant_ids[-1].location_id.name == '刀具线边库':
return functional_tool
for functional_tool in functional_tools:
if functional_tool.barcode_id.quant_ids[-1].location_id.name == '刀具房':
return functional_tool
return False
def assemble_single_print(self):
"""
todo 组装单打印
:return:
"""
@api.model_create_multi
def create(self, vals):
obj = super(FunctionalToolAssembly, self).create(vals)
if obj.loading_task_source:
code = self._get_code(obj.loading_task_source)
obj.assembly_order_code = code
return obj
class FunctionalToolDismantle(models.Model):
_name = 'sf.functional.tool.dismantle'
_inherit = ["barcodes.barcode_events_mixin", 'mail.thread']
_description = '功能刀具拆解'
def on_barcode_scanned(self, barcode):
"""
扫码
"""
# 对barcode进行校验是否为货位编码
if not re.match(r'^[A-Za-z0-9]+-[A-Za-z0-9]+-\d{3}-\d{3}$', barcode):
tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', barcode), ('functional_tool_status', '!=', '已拆除')])
if tool_id:
self.functional_tool_id = tool_id.id
else:
raise ValidationError('Rfid为【%s】的功能刀具不存在,请重新扫描!' % barcode)
else:
if self.dismantle_cause == '更换为其他刀具':
location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', barcode)])
if not location:
raise ValidationError('%s】该货位不存在,请重新扫码!' % barcode)
else:
if not location.product_id:
# 判断功能刀具存在哪些刀具物料需要录入库位
if self.chuck_product_id: # 夹头
if not self.chuck_freight_id:
self.chuck_freight_id = location.id
return True
if self.integral_product_id: # 整体式刀具
if not self.integral_freight_id:
self.integral_freight_id = location.id
return True
elif self.blade_product_id: # 刀片
if not self.blade_freight_id:
self.blade_freight_id = location.id
return True
if self.bar_product_id: # 刀杆
if not self.bar_freight_id:
self.bar_freight_id = location.id
return True
elif self.pad_product_id: # 刀盘
if not self.pad_freight_id:
self.pad_freight_id = location.id
return True
else:
# 判断货位存放的是那个刀具物料产品
if self.integral_product_id == location.product_id: # 整体式刀具
self.integral_freight_id = location.id
elif self.blade_product_id == location.product_id: # 刀片
self.blade_freight_id = location.id
elif self.bar_product_id == location.product_id: # 刀杆
self.bar_freight_id = location.id
elif self.pad_product_id == location.product_id: # 刀盘
self.pad_freight_id = location.id
elif self.chuck_product_id == location.product_id: # 夹头
self.chuck_freight_id = location.id
elif self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
raise ValidationError('该功能刀具因为%s拆解,无需录入库位' % self.dismantle_cause)
else:
raise ValidationError('该功能刀具因为%s拆解,无需录入库位' % self.dismantle_cause)
name = fields.Char('名称', related='functional_tool_id.name')
code = fields.Char('拆解单号', default=lambda self: self._get_code(), readonly=True)
def _get_code(self):
"""
自动生成拆解单编码
"""
new_time = str(fields.Date.today())
datetime = new_time[2:4] + new_time[5:7] + new_time[-2:]
functional_tool_dismantle = self.env['sf.functional.tool.dismantle'].sudo().search(
[('code', 'ilike', datetime)], limit=1, order="id desc")
if not functional_tool_dismantle:
num = "%03d" % 1
else:
m = int(functional_tool_dismantle.code[-3:]) + 1
num = "%03d" % m
return 'GNDJ-CJD-%s-%s' % (datetime, num)
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True,
domain=[('functional_tool_status', '!=', '已拆除'),
('current_location', '=', '刀具房')])
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
compute='_compute_functional_tool_num')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True)
diameter = fields.Float(string='刀具直径(mm)', compute='_compute_functional_tool_num', store=True)
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_functional_tool_num', store=True)
rfid = fields.Char('Rfid', compute='_compute_functional_tool_num', store=True)
rfid_dismantle = fields.Char('Rfid(已拆解)', readonly=True)
dismantle_cause = fields.Selection(
[('寿命到期报废', '寿命到期报废'), ('崩刀报废', '崩刀报废'), ('更换为其他刀具', '更换为其他刀具'),
('刀具需磨削', '刀具需磨削')], string='拆解原因', required=True, tracking=True)
dismantle_data = fields.Datetime('拆解日期', readonly=True)
dismantle_person = fields.Char('拆解人', readonly=True)
image = fields.Binary('图片', readonly=True)
scrap_id = fields.Char('报废单号', readonly=True)
grinding_id = fields.Char('磨削单号', readonly=True)
state = fields.Selection([('待拆解', '待拆解'), ('已拆解', '已拆解')], default='待拆解', tracking=True)
active = fields.Boolean('有效', default=True)
# 刀柄
handle_product_id = fields.Many2one('product.product', string='刀柄', compute='_compute_functional_tool_num',
store=True)
handle_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号',
related='handle_product_id.cutting_tool_model_id')
handle_brand_id = fields.Many2one('sf.machine.brand', string='刀柄品牌', related='handle_product_id.brand_id')
handle_rfid = fields.Char(string='刀柄Rfid', compute='_compute_functional_tool_num', store=True)
handle_lot_id = fields.Many2one('stock.lot', string='刀柄序列号', compute='_compute_functional_tool_num',
store=True)
scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False, tracking=True)
# 整体式
integral_product_id = fields.Many2one('product.product', string='整体式刀具',
compute='_compute_functional_tool_num', store=True)
integral_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号',
related='integral_product_id.cutting_tool_model_id')
integral_brand_id = fields.Many2one('sf.machine.brand', string='整体式刀具品牌',
related='integral_product_id.brand_id')
integral_lot_id = fields.Many2one('stock.lot', string='整体式刀具批次', compute='_compute_functional_tool_num',
store=True)
integral_freight_id = fields.Many2one('sf.shelf.location', '整体式刀具目标货位',
domain="[('product_id', 'in', (integral_product_id, False))]")
# 刀片
blade_product_id = fields.Many2one('product.product', string='刀片', compute='_compute_functional_tool_num',
store=True)
blade_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号',
related='blade_product_id.cutting_tool_model_id')
blade_brand_id = fields.Many2one('sf.machine.brand', string='刀片品牌', related='blade_product_id.brand_id')
blade_lot_id = fields.Many2one('stock.lot', string='刀片批次', compute='_compute_functional_tool_num', store=True)
blade_freight_id = fields.Many2one('sf.shelf.location', '刀片目标货位',
domain="[('product_id', 'in', (blade_product_id, False))]")
# 刀杆
bar_product_id = fields.Many2one('product.product', string='刀杆', compute='_compute_functional_tool_num',
store=True)
bar_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号',
related='bar_product_id.cutting_tool_model_id')
bar_brand_id = fields.Many2one('sf.machine.brand', string='刀杆品牌', related='bar_product_id.brand_id')
bar_lot_id = fields.Many2one('stock.lot', string='刀杆批次', compute='_compute_functional_tool_num', store=True)
bar_freight_id = fields.Many2one('sf.shelf.location', '刀杆目标货位',
domain="[('product_id', 'in', (bar_product_id, False))]")
# 刀盘
pad_product_id = fields.Many2one('product.product', string='刀盘', compute='_compute_functional_tool_num',
store=True)
pad_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号',
related='pad_product_id.cutting_tool_model_id')
pad_brand_id = fields.Many2one('sf.machine.brand', string='刀盘品牌', related='pad_product_id.brand_id')
pad_lot_id = fields.Many2one('stock.lot', string='刀盘批次', compute='_compute_functional_tool_num', store=True)
pad_freight_id = fields.Many2one('sf.shelf.location', '刀盘目标货位',
domain="[('product_id', 'in', (pad_product_id, False))]")
# 夹头
chuck_product_id = fields.Many2one('product.product', string='夹头', compute='_compute_functional_tool_num',
store=True)
chuck_type_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号',
related='chuck_product_id.cutting_tool_model_id')
chuck_brand_id = fields.Many2one('sf.machine.brand', string='夹头品牌', related='chuck_product_id.brand_id')
chuck_lot_id = fields.Many2one('stock.lot', string='夹头批次', compute='_compute_functional_tool_num', store=True)
chuck_freight_id = fields.Many2one('sf.shelf.location', '夹头目标货位',
domain="[('product_id', 'in', (chuck_product_id, False))]")
@api.onchange('functional_tool_id')
def _onchange_freight(self):
for item in self:
item.integral_freight_id = False
item.blade_freight_id = False
item.bar_freight_id = False
item.pad_freight_id = False
item.chuck_freight_id = False
@api.depends('functional_tool_id')
def _compute_functional_tool_num(self):
for item in self:
if item.functional_tool_id:
item.tool_groups_id = item.functional_tool_id.tool_groups_id.id
item.tool_type_id = item.functional_tool_id.sf_cutting_tool_type_id.id
item.diameter = item.functional_tool_id.functional_tool_diameter
item.knife_tip_r_angle = item.functional_tool_id.knife_tip_r_angle
item.rfid = item.functional_tool_id.rfid
item.handle_rfid = item.functional_tool_id.rfid
# 产品
item.handle_product_id = item.functional_tool_id.functional_tool_name_id.handle_product_id.id
item.integral_product_id = item.functional_tool_id.functional_tool_name_id.integral_product_id.id
item.blade_product_id = item.functional_tool_id.functional_tool_name_id.blade_product_id.id
item.bar_product_id = item.functional_tool_id.functional_tool_name_id.bar_product_id.id
item.pad_product_id = item.functional_tool_id.functional_tool_name_id.pad_product_id.id
item.chuck_product_id = item.functional_tool_id.functional_tool_name_id.chuck_product_id.id
# 批次/序列号
item.handle_lot_id = item.functional_tool_id.functional_tool_name_id.handle_code_id.id
item.integral_lot_id = item.functional_tool_id.functional_tool_name_id.integral_lot_id.id
item.blade_lot_id = item.functional_tool_id.functional_tool_name_id.blade_lot_id.id
item.bar_lot_id = item.functional_tool_id.functional_tool_name_id.bar_lot_id.id
item.pad_lot_id = item.functional_tool_id.functional_tool_name_id.pad_lot_id.id
item.chuck_lot_id = item.functional_tool_id.functional_tool_name_id.chuck_lot_id.id
else:
item.tool_groups_id = False
item.tool_type_id = False
item.diameter = 0
item.knife_tip_r_angle = 0
item.rfid = ''
item.handle_rfid = ''
item.handle_product_id = False
item.integral_product_id = False
item.blade_product_id = False
item.bar_product_id = False
item.pad_product_id = False
item.chuck_product_id = False
item.handle_lot_id = False
item.integral_lot_id = False
item.blade_lot_id = False
item.bar_lot_id = False
item.pad_lot_id = False
item.chuck_lot_id = False
def location_duplicate_check(self):
"""
目标货位去重校验
"""
if self.blade_freight_id:
if self.bar_freight_id:
if self.blade_freight_id == self.bar_freight_id:
raise ValidationError('【刀片】和【刀杆】的目标货位重复,请重新选择!')
elif self.pad_freight_id:
if self.blade_freight_id == self.pad_freight_id:
raise ValidationError('【刀片】和【刀盘】的目标货位重复,请重新选择!')
if self.chuck_freight_id:
if self.chuck_freight_id == self.integral_freight_id:
raise ValidationError('【夹头】和【整体式刀具】的目标货位重复,请重新选择!')
if self.chuck_freight_id == self.blade_freight_id:
raise ValidationError('【夹头】和【刀片】的目标货位重复,请重新选择!')
if self.chuck_freight_id == self.bar_freight_id:
raise ValidationError('【夹头】和【刀杆】的目标货位重复,请重新选择!')
if self.chuck_freight_id == self.pad_freight_id:
raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!')
def confirmation_disassembly(self):
logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
code = self.code
if self.functional_tool_id.functional_tool_status == '已拆除':
raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle)
# 对拆解的功能刀具进行校验,只有在刀具房的功能刀具才能拆解
if self.functional_tool_id.tool_room_num == 0:
raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % (
self.rfid, self.functional_tool_id.current_location))
# 目标重复校验
self.location_duplicate_check()
location = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
location_dest = self.env['stock.location'].search([('name', '=', '刀具房')])
# =================刀柄是否[报废]拆解=======
location_dest_scrap_ids = self.env['stock.location'].search([('name', 'in', ('Scrap', '报废'))])
if self.handle_rfid:
lot = self.env['stock.lot'].sudo().search([('rfid', '=', self.handle_rfid)])
if not lot:
raise ValidationError('Rfid为【%s】的功能刀具序列号不存在!' % self.handle_rfid)
functional_tool_assembly = self.functional_tool_id.functional_tool_name_id
if self.scrap_boolean:
# 刀柄报废 入库到Scrap
lot.create_stock_quant(location, location_dest_scrap_ids[-1], functional_tool_assembly.id, code,
functional_tool_assembly, functional_tool_assembly.tool_groups_id)
lot.tool_material_status = '报废'
else:
# 刀柄不报废 入库到刀具房
lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, code,
functional_tool_assembly, functional_tool_assembly.tool_groups_id)
lot.tool_material_status = '可用'
# ==============功能刀具[报废]拆解================
if self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
# 除刀柄外物料报废 入库到Scrap
if self.integral_product_id:
self.integral_product_id.dismantle_stock_moves(False, self.integral_lot_id, location,
location_dest_scrap_ids[-1], code)
elif self.blade_product_id:
self.blade_product_id.dismantle_stock_moves(False, self.blade_lot_id, location,
location_dest_scrap_ids[-1], code)
if self.bar_product_id:
self.bar_product_id.dismantle_stock_moves(False, self.bar_lot_id, location,
location_dest_scrap_ids[-1], code)
elif self.pad_product_id:
self.pad_product_id.dismantle_stock_moves(False, self.pad_lot_id, location,
location_dest_scrap_ids[-1], code)
if self.chuck_product_id:
self.chuck_product_id.dismantle_stock_moves(False, self.chuck_lot_id, location,
location_dest_scrap_ids[-1], code)
# ===========功能刀具[磨削]拆解==============
# elif self.dismantle_cause in ['刀具需磨削']:
# location_dest = self.env['stock.location'].search([('name', '=', '磨削房')])
# # 除刀柄外物料拆解 入库到具体库位
# if self.integral_product_id:
# self.integral_product_id.dismantle_stock_moves(False, location, location_dest)
# elif self.blade_product_id:
# self.blade_product_id.dismantle_stock_moves(False, location, location_dest)
# if self.bar_product_id:
# self.bar_product_id.dismantle_stock_moves(False, location, location_dest)
# elif self.pad_product_id:
# self.pad_product_id.dismantle_stock_moves(False, location, location_dest)
# if self.chuck_product_id:
# self.chuck_product_id.dismantle_stock_moves(False, location, location_dest)
# ==============功能刀具[更换,磨削]拆解==============
elif self.dismantle_cause in ['更换为其他刀具', '刀具需磨削']:
# 除刀柄外物料拆解 入库到具体货位
if self.integral_freight_id:
self.integral_product_id.dismantle_stock_moves(self.integral_freight_id, self.integral_lot_id, location,
location_dest, code)
elif self.blade_freight_id:
self.blade_product_id.dismantle_stock_moves(self.blade_freight_id, self.blade_lot_id, location,
location_dest, code)
if self.bar_freight_id:
self.bar_product_id.dismantle_stock_moves(self.bar_freight_id, self.bar_lot_id, location,
location_dest, code)
elif self.pad_freight_id:
self.pad_product_id.dismantle_stock_moves(self.pad_freight_id, self.pad_lot_id, location,
location_dest, code)
if self.chuck_freight_id:
self.chuck_product_id.dismantle_stock_moves(self.chuck_freight_id, self.chuck_lot_id, location,
location_dest, code)
# ===============删除功能刀具的Rfid字段的值 赋值给Rfid(已拆解)字段=====
self.functional_tool_id.write({
'rfid_dismantle': self.functional_tool_id.rfid,
'rfid': '',
'functional_tool_status': '已拆除'
})
# 修改拆解单的值
self.write({
'rfid_dismantle': self.rfid,
'dismantle_data': fields.Datetime.now(),
'dismantle_person': self.env.user.name,
'rfid': '',
'state': '已拆解'
})
logging.info('%s】刀具拆解成功!' % self.name)
class ProductProduct(models.Model):
_inherit = 'product.product'
def dismantle_stock_moves(self, shelf_location_id, lot_id, location_id, location_dest_id, code):
# 创建功能刀具拆解单产品库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': code,
'product_id': self.id,
'location_id': location_id.id,
'location_dest_id': location_dest_id.id,
'product_uom_qty': 1.00,
'state': 'done'
})
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.id,
'lot_id': lot_id.id,
'move_id': stock_move_id.id,
'destination_location_id': shelf_location_id.id if shelf_location_id else False,
'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0,
'state': 'done',
})
return stock_move_id, stock_move_line_id