diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 2184e7d1..77467962 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -972,7 +972,7 @@ class SfWorkOrderBarcodes(models.Model): # [('routing_type', '=', '装夹预调'), ('production_id', '=', self.production_id.id)]) workorder_old = self.env['mrp.workorder'].search([('rfid_code', '=', barcode)]) if workorder_old: - raise UserError('该托盘已绑定工件,请先解除绑定!!!') + raise UserError('该托盘已绑定【%s】制造订单,请先解除绑定!!!' % workorder_old.production_id.name) if workorder: if workorder.routing_type == '装夹预调': if workorder.state in ['done']: diff --git a/sf_sale/views/purchase_order_view.xml b/sf_sale/views/purchase_order_view.xml index f92658fc..90c9bd4b 100644 --- a/sf_sale/views/purchase_order_view.xml +++ b/sf_sale/views/purchase_order_view.xml @@ -94,7 +94,7 @@ {'readonly': ['&',('state', 'in', ['purchase']),('check_status','in', - ['pending','approved'])]} + ['approved'])]} diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 83b4b550..43baaab5 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import re + import logging from datetime import timedelta @@ -423,7 +425,8 @@ class FunctionalToolAssembly(models.Model): def _compute_integral_product_id(self): for item in self: if item.integral_freight_barcode: - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.integral_freight_barcode)]) + location = self.env['sf.shelf.location'].sudo().search( + [('barcode', '=', item.integral_freight_barcode)]) if location: item.integral_product_id = location.product_id.id else: @@ -442,7 +445,7 @@ class FunctionalToolAssembly(models.Model): @api.depends('blade_freight_barcode') def _compute_blade_product_id(self): for item in self: - if item.integral_freight_barcode: + if item.blade_freight_barcode: location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.blade_freight_barcode)]) if location: item.blade_product_id = location.product_id.id @@ -462,7 +465,7 @@ class FunctionalToolAssembly(models.Model): @api.depends('bar_freight_barcode') def _compute_bar_product_id(self): for item in self: - if item.integral_freight_barcode: + if item.bar_freight_barcode: location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.bar_freight_barcode)]) if location: item.bar_product_id = location.product_id.id @@ -482,7 +485,7 @@ class FunctionalToolAssembly(models.Model): @api.depends('pad_freight_barcode') def _compute_pad_product_id(self): for item in self: - if item.integral_freight_barcode: + if item.pad_freight_barcode: location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.pad_freight_barcode)]) if location: item.pad_product_id = location.product_id.id @@ -523,7 +526,7 @@ class FunctionalToolAssembly(models.Model): @api.depends('chuck_freight_barcode') def _compute_chuck_product_id(self): for item in self: - if item.integral_freight_barcode: + if item.chuck_freight_barcode: location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.chuck_freight_barcode)]) if location: item.chuck_product_id = location.product_id.id @@ -631,3 +634,285 @@ class FunctionalToolAssembly(models.Model): 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"] + _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') + + functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, + domain=[('functional_tool_status', '!=', '已拆除')]) + 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.Integer(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) + 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='待拆解') + 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) + scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False) + + # 整体式 + 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_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_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_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_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_freight_id = fields.Many2one('sf.shelf.location', '夹头目标货位', + domain="[('product_id', 'in', (chuck_product_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 + 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 + + def confirmation_disassembly(self): + logging.info('%s刀具确认开始拆解' % self.dismantle_cause) + if self.functional_tool_id.functional_tool_status == '已拆除': + raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle) + location = self.env['stock.location'].search([('name', '=', '刀具组装位置')]) + location_dest = self.env['stock.location'].search([('name', '=', '刀具房')]) + # =================刀柄是否报废拆解======= + location_dest_scrap = self.env['stock.location'].search([('name', '=', 'Scrap')]) + if self.handle_rfid: + lot = self.env['stock.lot'].sudo().search([('rfid', '=', 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, functional_tool_assembly.id, '功能刀具拆解', + functional_tool_assembly, functional_tool_assembly.tool_groups_id) + else: + # 刀柄不报废 入库到刀具房 + lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, '功能刀具拆解', + functional_tool_assembly, functional_tool_assembly.tool_groups_id) + # ==============功能刀具报废拆解================ + if self.dismantle_cause in ['寿命到期报废', '崩刀报废']: + # 除刀柄外物料报废 入库到Scrap + if self.integral_freight_id: + self.integral_product_id.dismantle_stock_moves(False, location, location_dest_scrap) + elif self.blade_freight_id: + self.blade_product_id.dismantle_stock_moves(False, location, location_dest_scrap) + if self.bar_freight_id: + self.bar_product_id.dismantle_stock_moves(False, location, location_dest_scrap) + elif self.pad_freight_id: + self.pad_product_id.dismantle_stock_moves(False, location, location_dest_scrap) + if self.chuck_freight_id: + self.chuck_product_id.dismantle_stock_moves(False, location, location_dest_scrap) + # ===========功能刀具磨削拆解============== + elif self.dismantle_cause in ['刀具需磨削']: + location_dest = self.env['stock.location'].search([('name', '=', '磨削房')]) + # 除刀柄外物料拆解 入库到具体库位 + if self.integral_freight_id: + self.integral_product_id.dismantle_stock_moves(False, location, location_dest) + elif self.blade_freight_id: + self.blade_product_id.dismantle_stock_moves(False, location, location_dest) + if self.bar_freight_id: + self.bar_product_id.dismantle_stock_moves(False, location, location_dest) + elif self.pad_freight_id: + self.pad_product_id.dismantle_stock_moves(False, location, location_dest) + if self.chuck_freight_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.barcode, location, + location_dest) + elif self.blade_freight_id: + self.blade_product_id.dismantle_stock_moves(self.blade_freight_id.barcode, location, location_dest) + if self.bar_freight_id: + self.bar_product_id.dismantle_stock_moves(self.bar_freight_id.barcode, location, location_dest) + elif self.pad_freight_id: + self.pad_product_id.dismantle_stock_moves(self.pad_freight_id.barcode, location, location_dest) + if self.chuck_freight_id: + self.chuck_product_id.dismantle_stock_moves(self.chuck_freight_id.barcode, location, location_dest) + # ===============删除功能刀具的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('刀具拆解成功!') + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + def dismantle_stock_moves(self, shelf_location_barcode, location_id, location_dest_id): + # 创建功能刀具拆解单产品库存移动记录 + stock_move_id = self.env['stock.move'].sudo().create({ + 'name': '功能刀具拆解', + 'product_id': self.id, + 'location_id': location_id.id, + 'location_dest_id': location_dest_id.id, + 'product_uom_qty': 1.00, + 'state': 'done' + }) + if shelf_location_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', shelf_location_barcode)]) + location.product_num = location.product_num + 1 + else: + location = False + # 创建移动历史记录 + stock_move_line_id = self.env['stock.move.line'].sudo().create({ + 'product_id': self.id, + 'move_id': stock_move_id.id, + 'current_location_id': location.id or False, + 'install_tool_time': fields.Datetime.now(), + 'qty_done': 1.0, + 'state': 'done', + }) + + return stock_move_id, stock_move_line_id diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py index c37d5317..eae00080 100644 --- a/sf_tool_management/models/functional_tool.py +++ b/sf_tool_management/models/functional_tool.py @@ -14,6 +14,7 @@ class FunctionalCuttingToolEntity(models.Model): tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') code = fields.Char('编码') rfid = fields.Char('Rfid', readonly=True) + rfid_dismantle = fields.Char('Rfid(已拆解)', readonly=True) name = fields.Char('名称') tool_name_id = fields.Many2one('sf.tool.inventory', '功能刀具名称') sf_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号') @@ -44,7 +45,7 @@ class FunctionalCuttingToolEntity(models.Model): active = fields.Boolean(string='已归档', default=True) - @api.depends('barcode_id.quant_ids') + @api.depends('barcode_id.quant_ids', 'functional_tool_status') def _compute_current_location_id(self): for record in self: if record.barcode_id.quant_ids: @@ -60,6 +61,12 @@ class FunctionalCuttingToolEntity(models.Model): else: record.current_location_id = False record.current_location = False + if record.functional_tool_status == '已拆除': + record.current_location_id = False + record.current_location = False + record.tool_room_num = 0 + record.line_edge_knife_library_num = 0 + record.machine_knife_library_num = 0 def get_location_num(self): """ @@ -184,7 +191,8 @@ class FunctionalCuttingToolEntity(models.Model): stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')]) # 创建功能刀具该批次/序列号 库存移动和移动历史 self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id, - self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id) + self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id, + self.functional_tool_name_id.tool_groups_id) # ==========刀具组接口========== # def _register_functional_tool_groups(self, obj): diff --git a/sf_tool_management/models/maintenance_equipment.py b/sf_tool_management/models/maintenance_equipment.py index 9932d135..fef6c67c 100644 --- a/sf_tool_management/models/maintenance_equipment.py +++ b/sf_tool_management/models/maintenance_equipment.py @@ -110,6 +110,8 @@ class StockLot(models.Model): record.tool_material_status = '可用' elif record.quant_ids[-1].location_id.name == '刀具组装位置': record.tool_material_status = '在用' + elif record.quant_ids[-1].location_id.name == 'Scrap': + record.tool_material_status = '报废' else: record.tool_material_status = '未入库' if record.tool_material_search_id: diff --git a/sf_tool_management/models/tool_material_search.py b/sf_tool_management/models/tool_material_search.py index bfb8d64b..ee60c048 100644 --- a/sf_tool_management/models/tool_material_search.py +++ b/sf_tool_management/models/tool_material_search.py @@ -39,9 +39,7 @@ class ToolMaterial(models.Model): usable_num += quant.quantity elif location == '刀具组装位置': have_been_used_num += quant.quantity - elif location == '进货': - pass - elif location != 'Vendors': + elif location == 'Scrap': scrap_num += quant.quantity record.usable_num = usable_num record.have_been_used_num = have_been_used_num diff --git a/sf_tool_management/security/ir.model.access.csv b/sf_tool_management/security/ir.model.access.csv index 3a7b4589..79800637 100644 --- a/sf_tool_management/security/ir.model.access.csv +++ b/sf_tool_management/security/ir.model.access.csv @@ -30,4 +30,8 @@ access_sf_tool_material_search,sf.tool.material.search,model_sf_tool_material_se access_sf_tool_material_search_group_plan_dispatch,sf.tool.material.search,model_sf_tool_material_search,sf_base.group_plan_dispatch,1,0,0,0 access_sf_fixture_material_search,sf.fixture.material.search,model_sf_fixture_material_search,sf_base.group_sf_order_user,1,0,0,0 -access_sf_fixture_material_search_group_plan_dispatch,sf.fixture.material.search,model_sf_fixture_material_search,sf_base.group_plan_dispatch,1,0,0,0 \ No newline at end of file +access_sf_fixture_material_search_group_plan_dispatch,sf.fixture.material.search,model_sf_fixture_material_search,sf_base.group_plan_dispatch,1,0,0,0 + + +access_sf_functional_tool_dismantle_group_sf_tool_user,sf.functional.tool.dismantle,model_sf_functional_tool_dismantle,sf_base.group_sf_tool_user,1,1,1,0 +access_sf_functional_tool_dismantle_group_plan_dispatch,sf.functional.tool.dismantle,model_sf_functional_tool_dismantle,sf_base.group_plan_dispatch,1,0,0,0 diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml index 82fbd8bc..53e050d9 100644 --- a/sf_tool_management/views/functional_tool_views.xml +++ b/sf_tool_management/views/functional_tool_views.xml @@ -85,7 +85,10 @@ - + + @@ -202,6 +205,9 @@ + + + @@ -218,6 +224,8 @@ sf.functional.cutting.tool.entity tree,form,search + + {'search_default_no_state_removed':1} diff --git a/sf_tool_management/views/menu_view.xml b/sf_tool_management/views/menu_view.xml index 13a12725..8ddee8eb 100644 --- a/sf_tool_management/views/menu_view.xml +++ b/sf_tool_management/views/menu_view.xml @@ -14,69 +14,111 @@ parent="mrp.menu_mrp_root" sequence="20"/> - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index 46c77b82..1db89ddb 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -766,5 +766,187 @@ {'search_default_no_assemble_status':1} + + + + + 功能刀具拆解 + sf.functional.tool.dismantle + + + + + + + + + + + + + + + + + + 功能刀具拆解 + sf.functional.tool.dismantle + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + sf.functional.tool.dismantle + + + + + + + + + + + + + + + + + 功能刀具拆解 + ir.actions.act_window + sf.functional.tool.dismantle + tree,form,search + + {'search_default_no_dismantle_state':1} + + + diff --git a/sf_tool_management/views/tool_material_search.xml b/sf_tool_management/views/tool_material_search.xml index ee63ba26..d4772244 100644 --- a/sf_tool_management/views/tool_material_search.xml +++ b/sf_tool_management/views/tool_material_search.xml @@ -94,12 +94,5 @@ sf.tool.material.search tree,form - diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index 979d8efe..a97e7274 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -243,11 +243,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('integral_freight_barcode') def _compute_integral_product_id(self): - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.integral_freight_barcode)]) - if location: - self.integral_product_id = location.product_id.id - else: - self.integral_product_id = False + if self.integral_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.integral_freight_barcode)]) + if location: + self.integral_product_id = location.product_id.id + else: + self.integral_product_id = False # ===============刀片型号==================== blade_freight_barcode = fields.Char('刀片货位') @@ -261,11 +262,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('blade_freight_barcode') def _compute_blade_product_id(self): - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.blade_freight_barcode)]) - if location: - self.blade_product_id = location.product_id.id - else: - self.blade_product_id = False + if self.blade_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.blade_freight_barcode)]) + if location: + self.blade_product_id = location.product_id.id + else: + self.blade_product_id = False # ====================刀杆型号================== bar_freight_barcode = fields.Char('刀杆货位') @@ -279,11 +281,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('bar_freight_barcode') def _compute_bar_product_id(self): - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.bar_freight_barcode)]) - if location: - self.bar_product_id = location.product_id.id - else: - self.bar_product_id = False + if self.bar_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.bar_freight_barcode)]) + if location: + self.bar_product_id = location.product_id.id + else: + self.bar_product_id = False # ===============刀盘型号=================== pad_freight_barcode = fields.Char('刀盘货位') @@ -297,11 +300,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('pad_freight_barcode') def _compute_pad_product_id(self): - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.pad_freight_barcode)]) - if location: - self.pad_product_id = location.product_id.id - else: - self.pad_product_id = False + if self.pad_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.pad_freight_barcode)]) + if location: + self.pad_product_id = location.product_id.id + else: + self.pad_product_id = False # ================刀柄型号=============== handle_freight_rfid = fields.Char('刀柄Rfid', compute='_compute_rfid') @@ -335,11 +339,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('chuck_freight_barcode') def _compute_chuck_product_id(self): - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.chuck_freight_barcode)]) - if location: - self.chuck_product_id = location.product_id.id - else: - self.chuck_product_id = False + if self.chuck_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.chuck_freight_barcode)]) + if location: + self.chuck_product_id = location.product_id.id + else: + self.chuck_product_id = False # ======================================== @@ -398,7 +403,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): after_name_id = fields.Many2one('sf.tool.inventory', string='功能刀具名称', required=True) barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号') rfid = fields.Char('Rfid', compute='_compute_rfid') - tool_code = fields.Char(string='功能刀具编码', compute='_compute_tool_code') + code = fields.Char(string='功能刀具编码', compute='_compute_code') after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', compute='_compute_name', store=True) after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='组装后功能刀具类型') @@ -443,7 +448,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('after_assembly_functional_tool_type_id', 'integral_specification_id', 'bar_specification_id', 'pad_specification_id', 'handle_specification_id', 'after_assembly_tool_loading_length') - def _compute_tool_code(self): + def _compute_code(self): for obj in self: str_1 = 'GNDJ-%s' % obj.after_assembly_functional_tool_type_id.code str_2 = '' @@ -462,11 +467,11 @@ class FunctionalToolAssemblyOrder(models.TransientModel): obj.pad_specification_id.cut_depth_max, obj.handle_specification_id.total_length, ) else: - obj.tool_code = str_2 + obj.code = str_2 return True - obj.tool_code = str_2 + str(self._get_code(str_2)) + obj.code = str_2 + str(self._get_code(str_2)) else: - obj.tool_code = str_2 + obj.code = str_2 def _get_code(self, str_2): functional_tool_assembly = self.env['sf.functional.cutting.tool.entity'].sudo().search( @@ -613,7 +618,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): def get_desc_1(self, stock_lot): return { 'barcode_id': stock_lot.id, - 'code': self.tool_code, + 'code': self.code, 'rfid': self.rfid, 'tool_groups_id': self.after_tool_groups_id.id, 'integral_freight_barcode': self.integral_freight_barcode, @@ -650,7 +655,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): def get_desc_2(self, stock_lot, functional_tool_assembly_id): return { 'barcode_id': stock_lot.id, - 'code': self.tool_code, + 'code': self.code, 'name': self.after_name_id.name, 'tool_name_id': self.after_name_id.id, 'rfid': self.rfid, @@ -713,7 +718,7 @@ class StockPicking(models.Model): 'functional_tool_type_id': obj.functional_tool_type_id.id, 'diameter': obj.after_assembly_functional_tool_diameter, 'knife_tip_r_angle': obj.after_assembly_knife_tip_r_angle, - 'code': obj.tool_code, + 'code': obj.code, 'rfid': obj.rfid, 'functional_tool_name': obj.after_assembly_functional_tool_name, 'tool_groups_id': obj.after_tool_groups_id.id @@ -757,7 +762,7 @@ class ProductProduct(models.Model): stock_location_id = self.env['stock.location'].search([('name', '=', '组装后')]) # 创建功能刀具该批次/序列号 库存移动和移动历史 stock_lot.create_stock_quant(location_inventory_id, stock_location_id, functional_tool_assembly.id, - '功能刀具组装', obj) + '功能刀具组装', obj, obj.after_tool_groups_id) return stock_lot @@ -791,7 +796,7 @@ class ProductProduct(models.Model): location_inventory_id = tool_material.quant_ids.location_id[-1] stock_location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')]) # 创建功能刀具该批次/序列号 库存移动和移动历史 - tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, '功能刀具组装', False) + tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, '功能刀具组装', False, False) def material_stock_moves(self, shelf_location_barcode): # 创建库存移动记录 @@ -814,16 +819,19 @@ class ProductProduct(models.Model): 'qty_done': 1.0, 'state': 'done', }) - - location.product_num = location.product_num - 1 - + if location.product_num > 0: + location.product_num = location.product_num - 1 + else: + raise ValidationError( + '【%s】货位的【%s】产品库存数量为零,请采购入库后再重新组装!' % (location.barcode, location.product_id.name)) return stock_move_id, stock_move_line_id class StockLot(models.Model): _inherit = 'stock.lot' - def create_stock_quant(self, location_inventory_id, stock_location_id, functional_tool_assembly_id, name, obj): + def create_stock_quant(self, location_inventory_id, stock_location_id, functional_tool_assembly_id, name, obj, + tool_groups_id): """ 对功能刀具组装过程的功能刀具和刀具物料进行库存移动,以及创建移动历史 """ @@ -850,10 +858,10 @@ class StockLot(models.Model): '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.tool_code, + '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 obj else obj.after_tool_groups_id.id + 'tool_groups_id': False if not tool_groups_id else tool_groups_id.id }) return stock_move_id, stock_move_line_id diff --git a/sf_tool_management/wizard/wizard_view.xml b/sf_tool_management/wizard/wizard_view.xml index 0eb2a77f..636f94f7 100644 --- a/sf_tool_management/wizard/wizard_view.xml +++ b/sf_tool_management/wizard/wizard_view.xml @@ -334,7 +334,7 @@ - +