1、功能刀具组装单添加对应调拨单跳转按钮;功能刀具拆解单添加调拨单跳转按钮和功能刀具移动跳转按钮;2、功能刀具拆解模型,form视图添加报废page页存放刀具物料报废单,优化拆解流程添加功能刀具拆解移动记录;3、功能刀具出入库列表视图添加拆解单跳转链接;4、功能刀具安全库存模型添加名称唯一验证,优化字段计算方法;5、优化功能刀具同步到cloud的同步接口,解决编码问题;

This commit is contained in:
yuxianghui
2024-07-03 17:17:48 +08:00
parent cbc8a41984
commit 4a86871039
5 changed files with 158 additions and 66 deletions

View File

@@ -669,6 +669,20 @@ class FunctionalToolAssembly(models.Model):
:return:
"""
picking_num = fields.Integer('调拨单数量', compute='compute_picking_num', store=True)
@api.depends('assemble_status')
def compute_picking_num(self):
for item in self:
picking_ids = self.env['stock.picking'].sudo().search([('origin', '=', item.assembly_order_code)])
item.picking_num = len(picking_ids)
def open_tool_stock_picking(self):
action = self.env.ref('stock.action_picking_tree_all')
result = action.read()[0]
result['domain'] = [('origin', '=', self.assembly_order_code)]
return result
@api.model_create_multi
def create(self, vals):
obj = super(FunctionalToolAssembly, self).create(vals)
@@ -758,7 +772,7 @@ class FunctionalToolDismantle(models.Model):
num = "%03d" % m
return 'GNDJ-CJD-%s-%s' % (datetime, num)
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True,
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True,
domain=[('functional_tool_status', '!=', '已拆除'),
('current_location', '=', '刀具房')])
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
@@ -778,6 +792,16 @@ class FunctionalToolDismantle(models.Model):
scrap_ids = fields.One2many('stock.scrap', 'functional_tool_dismantle_id', string='报废单号', readonly=True)
grinding_id = fields.Char('磨削单号', readonly=True)
picking_id = fields.Many2one('stock.picking', string='刀具物料调拨单')
picking_num = fields.Integer('调拨单数量', default=0, compute='compute_picking_num', store=True)
@api.depends('picking_id')
def compute_picking_num(self):
for item in self:
if item.picking_id:
item.picking_num = 1
else:
item.picking_num = 0
state = fields.Selection([('待拆解', '待拆解'), ('已拆解', '已拆解')], default='待拆解', tracking=True)
active = fields.Boolean('有效', default=True)
@@ -791,7 +815,14 @@ class FunctionalToolDismantle(models.Model):
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)
scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False, tracking=True, compute='compute_scrap_boolean',
store=True)
@api.depends('dismantle_cause')
def compute_scrap_boolean(self):
for item in self:
if item.dismantle_cause not in ['寿命到期报废', '崩刀报废']:
item.scrap_boolean = False
# 整体式
integral_product_id = fields.Many2one('product.product', string='整体式刀具',
@@ -974,20 +1005,19 @@ class FunctionalToolDismantle(models.Model):
if self.chuck_freight_id:
datas['picking'].append({'lot_id': self.chuck_lot_id, 'destination': self.chuck_freight_id})
self.create_tool_picking_scrap(datas)
# ===============修改功能刀具数据=====
# ===============创建功能刀具拆解移动记录=====
self.env['stock.move'].create_functional_tool_stock_move(self)
# 修改功能刀具数据
self.functional_tool_id.write({
'rfid_dismantle': self.functional_tool_id.rfid,
'rfid': '',
'functional_tool_status': '已拆除'
})
# 创建功能刀具拆解移动记录
location_dismantle_id = self.env['stock.location'].search([('name', '=', '拆解')])
# 修改拆解单的值
self.write({
'rfid_dismantle': self.rfid,
'dismantle_data': fields.Datetime.now(),
'dismantle_person': self.env.user.name,
'rfid': '',
'rfid': '%s(已拆解)' % self.rfid,
'state': '已拆解'
})
logging.info('%s】刀具拆解成功!' % self.name)
@@ -1001,6 +1031,7 @@ class FunctionalToolDismantle(models.Model):
self.env['stock.scrap'].create_tool_dismantle_stock_scrap(data['lot_id'], self)
if picking_data:
picking_id = self.env['stock.picking'].create_tool_dismantle_picking(self)
self.picking_id = picking_id.id
self.env['stock.move'].create_tool_stock_move({'data': picking_data, 'picking_id': picking_id})
# 将刀具物料出库库单的状态更改为就绪
picking_id.action_confirm()
@@ -1010,6 +1041,27 @@ class FunctionalToolDismantle(models.Model):
picking_id.action_set_quantities_to_reservation()
picking_id.button_validate()
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 open_function_tool_stock_move_line(self):
action = self.env.ref('sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_act')
result = action.read()[0]
result['domain'] = [('functional_tool_dismantle_id', '=', self.id), ('qty_done', '>', 0)]
return result
def open_tool_stock_picking(self):
action = self.env.ref('stock.action_picking_tree_all')
result = action.read()[0]
result['domain'] = [('origin', '=', self.code)]
return result
class StockPicking(models.Model):
_inherit = 'stock.picking'
@@ -1073,38 +1125,39 @@ class StockMove(models.Model):
})
return True
def create_functional_tool_stock_move(self, location_inventory_id, stock_location_id, functional_tool_assembly_id,
name, obj,
tool_groups_id):
def create_functional_tool_stock_move(self, dismantle_id):
"""
对功能刀具拆解过程的功能刀具进行库存移动,以及创建移动历史
"""
location_dismantle_id = self.env['stock.location'].search([('name', '=', '拆解')])
if not location_dismantle_id:
raise ValidationError('缺少名称为【拆解】的仓库管理地点')
tool_id = dismantle_id.functional_tool_id
# 创建库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': name,
'product_id': self.product_id.id,
'location_id': location_inventory_id.id,
'location_dest_id': stock_location_id.id,
'name': dismantle_id.code,
'product_id': tool_id.barcode_id.product_id.id,
'location_id': tool_id.current_location_id.id,
'location_dest_id': location_dismantle_id.id,
'product_uom_qty': 1.00,
'state': 'done'
})
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.product_id.id,
'functional_tool_name_id': functional_tool_assembly_id,
'lot_id': self.id,
'product_id': tool_id.barcode_id.product_id.id,
'functional_tool_dismantle_id': dismantle_id.id,
'lot_id': tool_id.barcode_id.id,
'move_id': stock_move_id.id,
'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0,
'state': 'done',
'functional_tool_type_id': False if not obj else obj.functional_tool_type_id.id,
'diameter': None if not obj else obj.after_assembly_functional_tool_diameter,
'knife_tip_r_angle': None if not obj else obj.after_assembly_knife_tip_r_angle,
'code': '' if not obj else obj.code,
'rfid': '' if not obj else obj.rfid,
'functional_tool_name': '' if not obj else obj.after_assembly_functional_tool_name,
'tool_groups_id': False if not tool_groups_id else tool_groups_id.id
'functional_tool_type_id': tool_id.sf_cutting_tool_type_id.id,
'diameter': tool_id.functional_tool_diameter,
'knife_tip_r_angle': tool_id.knife_tip_r_angle,
'code': tool_id.code,
'rfid': tool_id.rfid,
'functional_tool_name': tool_id.name,
'tool_groups_id': tool_id.tool_groups_id.id
})
return stock_move_id, stock_move_line_id

View File

@@ -252,9 +252,7 @@ class FunctionalCuttingToolEntity(models.Model):
def open_safety_stock(self):
action = self.env.ref('sf_tool_management.sf_real_time_distribution_of_functional_tools_view_act')
result = action.read()[0]
result['domain'] = [('name', '=', self.name), ('diameter', '=', self.functional_tool_diameter),
('knife_tip_r_angle', '=', self.knife_tip_r_angle),
('coarse_middle_thin', '=', self.coarse_middle_thin)]
result['domain'] = [('id', '=', self.safe_inventory_id.id)]
return result
def tool_inventory_displacement_out(self):
@@ -372,6 +370,7 @@ class StockMoveLine(models.Model):
_order = 'date desc'
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单')
functional_tool_dismantle_id = fields.Many2one('sf.functional.tool.dismantle', string='功能刀具拆解单')
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
group_expand='_read_group_functional_tool_type_id')
functional_tool_name = fields.Char('刀具名称')
@@ -392,6 +391,9 @@ class StockMoveLine(models.Model):
if self.functional_tool_name_id:
action = self.functional_tool_name_id.action_open_reference1()
return action
if self.functional_tool_dismantle_id:
action = self.functional_tool_dismantle_id.action_open_reference1()
return action
elif self.move_id:
action = self.move_id.action_open_reference()
if action['res_model'] != 'stock.move':
@@ -409,13 +411,14 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
_inherit = ['mail.thread']
_description = '功能刀具安全库存'
name = fields.Char('名称', readonly=True, compute='_compute_name', store=True)
name = fields.Char('名称', compute='_compute_num', store=True)
functional_name_id = fields.Many2one('sf.tool.inventory', string='功能刀具名称', required=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=False, required=True)
sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False,
group_expand='_read_mrs_cutting_tool_type_ids', store=True)
diameter = fields.Float(string='刀具直径(mm)', readonly=False)
knife_tip_r_angle = fields.Float(string='尖R角(mm)', readonly=False)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_num', store=True)
sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
compute='_compute_num', store=True,
group_expand='_read_mrs_cutting_tool_type_ids')
diameter = fields.Float(string='具直径(mm)', compute='_compute_num', store=True)
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_num', store=True)
tool_stock_num = fields.Integer(string='刀具房数量', compute='_compute_stock_num', store=True)
side_shelf_num = fields.Integer(string='线边刀库数量', compute='_compute_stock_num', store=True)
on_tool_stock_num = fields.Integer(string='机内刀库数量', compute='_compute_stock_num', store=True)
@@ -460,22 +463,18 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
active = fields.Boolean(string='已归档', default=True)
@api.onchange('functional_name_id')
def _onchange_num(self):
@api.depends('functional_name_id', 'functional_name_id.diameter', 'functional_name_id.angle',
'functional_name_id.functional_cutting_tool_model_id')
def _compute_num(self):
for item in self:
if item.functional_name_id:
item.tool_groups_id = item.functional_name_id.tool_groups_id.id
item.sf_cutting_tool_type_id = item.functional_name_id.functional_cutting_tool_model_id.id
item.diameter = item.functional_name_id.diameter
item.knife_tip_r_angle = item.functional_name_id.angle
@api.depends('functional_name_id')
def _compute_name(self):
for obj in self:
if obj.tool_groups_id:
obj.name = obj.functional_name_id.name
item.name = item.functional_name_id.name
else:
obj.sudo().name = ''
item.sudo().name = ''
@api.constrains('min_stock_num', 'max_stock_num')
def _check_stock_num(self):
@@ -583,4 +582,10 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
for vals in vals_list:
vals['status_create'] = False
records = super(RealTimeDistributionOfFunctionalTools, self).create(vals_list)
for item in records:
if item:
record = self.search([('functional_name_id', '=', item.functional_name_id.id)])
if len(record) > 1:
raise ValidationError(
'功能刀具名称为【%s】的安全库存已经存在,请勿重复创建!!!' % item.functional_name_id.name)
return records

View File

@@ -37,14 +37,10 @@ class ToolDatasync(models.Model):
def _cron_tool_datasync_all(self):
try:
self.env['stock.lot'].sudo().sync_enroll_tool_material_stock_all()
self.env['stock.lot'].sudo().sync_enroll_fixture_material_stock_all()
self.env['sf.tool.material.search'].sudo().sync_enroll_tool_material_all()
self.env['stock.lot'].sudo().sync_enroll_tool_material_stock_all()
self.env['sf.fixture.material.search'].sudo().sync_enroll_fixture_material_all()
self.env['stock.lot'].sudo().sync_enroll_fixture_material_stock_all()
self.env['sf.functional.cutting.tool.entity'].sudo().esync_enroll_functional_tool_entity_all()
logging.info("已全部同步完成!!!")
# self.env['sf.functional.tool.warning'].sudo().sync_enroll_functional_tool_warning_all()
@@ -106,7 +102,7 @@ class StockLot(models.Model):
logging.info("没有刀具物料序列号信息")
except Exception as e:
logging.info("刀具物料序列号同步失败:%s" % e)
class ToolMaterial(models.Model):
_inherit = 'sf.tool.material.search'
@@ -198,7 +194,7 @@ class FunctionalCuttingToolEntity(models.Model):
for item in objs_all:
val = {
'id': item.id,
'code': item.code,
'code': False if not item.code else item.code.split('-', 1)[1],
'name': item.name,
'rfid': item.rfid,
'tool_groups_name': item.tool_groups_id.name,

View File

@@ -29,7 +29,6 @@
<field name="current_location" string="当前位置"/>
<field name="current_location_id" invisible="1"/>
<field name="current_location" optional="hide"/>
<field name="sf_cutting_tool_type_id" invisible="True"/>
</tree>
</field>
@@ -61,13 +60,9 @@
</button>
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_stock_move_line"
icon="fa-list-ul"
type="object">
<div class="o_field_widget o_stat_info">
<span>
出库入库记录
</span>
</div>
<i class="fa fa-fw o_button_icon fa-exchange"/>
<span>出库入库记录</span>
</button>
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_safety_stock"
@@ -482,18 +477,19 @@
<field name="reference" string="单据号"/>
<field name="lot_id" invisible="1"/>
<field name="rfid"/>
<field name="functional_tool_name_id" optional="hide"/>
<field name="functional_tool_name" string="功能刀具名称"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="install_tool_time"/>
<field name="location_id"/>
<field name="current_location_id"/>
<field name="location_dest_id"/>
<field name="destination_location_id"/>
<field name="date"/>
<field name="qty_done" string="数量"/>
<field name="functional_tool_type_id" invisible="True"/>
<field name="functional_tool_type_id" invisible="1"/>
<field name="functional_tool_name_id" invisible="1"/>
<field name="functional_tool_dismantle_id" invisible="1"/>
<field name="install_tool_time" invisible="1"/>
<!-- <button name="enroll_functional_tool_move" string="安全库存注册" type="object" class="btn-primary"/>-->
</tree>
</field>

View File

@@ -407,6 +407,7 @@
<field name="plan_execute_status"/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel>
<field name="plan_execute_status" string="状态" enable_counters="1" icon="fa-filter"/>
<field name="production_line_id" string="生产线" enable_counters="1" icon="fa-filter"/>
<field name="functional_tool_type_id" string="功能刀具类型" enable_counters="1"
icon="fa-filter"/>
@@ -476,6 +477,17 @@
<field name="assemble_status" widget="statusbar" statusbar_visible="0,1"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="open_tool_stock_picking" icon="fa-truck" type="object"
attrs="{'invisible': [('assemble_status', '!=', '1')]}">
<div name="delivery_count" class="o_field_widget o_readonly_modifier o_field_statinfo">
<span class="o_stat_info o_stat_value">
<field name="picking_num"/>
</span>
<span class="o_stat_text">调拨</span>
</div>
</button>
</div>
<div class="oe_title">
<h1>
<field name="assembly_order_code"/>
@@ -763,10 +775,25 @@
<form>
<header>
<button string="确认拆解" name="confirmation_disassembly" type="object" class="btn-primary"
confirm="是否确认拆解" attrs="{'invisible': [('state', '=', '已拆解')]}"/>
confirm="是否确认拆解" attrs="{'invisible': [('state', '!=', '已拆解')]}"/>
<field name="state" widget="statusbar" statusbar_visible="待拆解,已拆解"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" name="open_tool_stock_picking" icon="fa-truck" type="object"
attrs="{'invisible':[('state', '!=', '已拆解')]}">
<div name="delivery_count" class="o_field_widget o_readonly_modifier o_field_statinfo">
<span class="o_stat_info o_stat_value">
<field name="picking_num"/>
</span>
<span class="o_stat_text">调拨</span>
</div>
</button>
<button class="oe_stat_button" name="open_function_tool_stock_move_line" icon="fa-exchange"
type="object">
<span>功能刀具移动</span>
</button>
</div>
<div class="oe_title">
<h1>
<field name="code"/>
@@ -777,12 +804,13 @@
<group>
<field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具"
options="{'no_create': True}" attrs="{'readonly': [('state', '=', '已拆解')]}"/>
<field name="rfid" attrs="{'invisible': [('state', '=', '已拆解')]}"/>
<field name="rfid_dismantle" attrs="{'invisible': [('state', '!=', '已拆解')]}"/>
<field name="rfid" attrs="{'invisible': [('rfid', '=', '')]}"/>
<field name="rfid_dismantle" attrs="{'invisible': [('rfid_dismantle', '=', False)]}"/>
<field name="tool_type_id"/>
<field name="tool_groups_id"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="picking_id" invisible="1"/>
</group>
<group>
<field name="image"/>
@@ -883,8 +911,22 @@
</group>
</group>
</page>
<page string="报废" attrs="{'invisible':[('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<field name="scrap_ids"/>
<page string="报废"
attrs="{'invisible':[('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<field name="scrap_ids">
<tree>
<field name="name"/>
<field name="product_id"/>
<field name="lot_id"/>
<field name="location_id"/>
<field name="scrap_location_id"/>
<field name="scrap_qty"/>
<field name="product_uom_id"/>
<field name="date_done"/>
<field name="state" widget="badge" decoration-success="state == 'done'"
decoration-muted="state == 'draft'"/>
</tree>
</field>
</page>
<page string="其他">
<group>