diff --git a/sf_dlm_management/views/product_template_management_view.xml b/sf_dlm_management/views/product_template_management_view.xml index 453de6a3..94fc6b45 100644 --- a/sf_dlm_management/views/product_template_management_view.xml +++ b/sf_dlm_management/views/product_template_management_view.xml @@ -10,6 +10,7 @@ + diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index d9839ae4..8a39696d 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -57,7 +57,7 @@ class MrpProduction(models.Model): production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], string='上/下产线', default='待上产线') - manual_quotation = fields.Boolean('人工编程', default=False) + manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) @api.depends( 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index e9648062..9627a0f7 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -46,7 +46,7 @@ class ResMrpWorkOrder(models.Model): ], string="工序类型") results = fields.Char('结果') - manual_quotation = fields.Boolean('人工编程', default=False) + manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) @api.onchange('users_ids') def get_user_permissions(self): diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index f3cba150..52f1fc9d 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -10,7 +10,6 @@ from OCC.Extend.DataExchange import read_step_file from OCC.Extend.DataExchange import write_stl_file - class ResProductMo(models.Model): _inherit = 'product.template' @@ -522,6 +521,9 @@ class ResProductMo(models.Model): string='注册状态', default='未注册') industry_code = fields.Char('行业编码', readonly=True) + # bfm下单 + manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) + @api.constrains('tool_length') def _check_tool_length_size(self): if self.tool_length > 1000000: @@ -616,6 +618,7 @@ class ResProductMo(models.Model): 'process_parameters_code') else self.get_process_parameters_id(item['process_parameters_code']), 'model_remark': item['remark'], 'default_code': '%s-%s' % (order_number, i), + 'manual_quotation': item['manual_quotation'] or False, 'active': True, } copy_product_id.sudo().write(vals) diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 56391077..01c3de46 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import logging + from datetime import timedelta from odoo import SUPERUSER_ID from odoo import fields, models, api @@ -191,7 +193,7 @@ class CAMWorkOrderProgramKnifePlan(models.Model): 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='刀位号', required=True, + 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) @@ -201,19 +203,20 @@ class CAMWorkOrderProgramKnifePlan(models.Model): barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', domain=[('product_id.name', '=', '功能刀具')]) - functional_tool_name = fields.Char(string='功能刀具名称', compute='_compute_functional_tool_name') - functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False) - tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组') - diameter = fields.Integer(string='刀具直径(mm)', readonly=False) - tool_included_angle = fields.Float(string='刀尖R角(mm)', readonly=False) - tool_loading_length = fields.Float(string='总长度(mm)', readonly=False) + 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.Integer(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)', 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') @@ -229,15 +232,24 @@ class CAMWorkOrderProgramKnifePlan(models.Model): active = fields.Boolean(string='已归档', default=True) - @api.depends('diameter', 'tool_included_angle', 'tool_groups_id') - def _compute_functional_tool_name(self): - for obj in self: - if obj.tool_groups_id: - obj.functional_tool_name = '%s-D%sR%s' % ( - obj.tool_groups_id.name, obj.diameter, - obj.tool_included_angle) + @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: - obj.functional_tool_name = None + 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): @@ -311,10 +323,9 @@ class CAMWorkOrderProgramKnifePlan(models.Model): 根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划 """ status = False - if cnc_processing.functional_tool_type_id and cnc_processing.cutting_tool_name: + if cnc_processing.cutting_tool_name: functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search( - [('sf_cutting_tool_type_id', '=', cnc_processing.functional_tool_type_id.id), - ('name', '=', cnc_processing.cutting_tool_name)]) + [('name', '=', cnc_processing.cutting_tool_name)]) if functional_tools: for functional_tool in functional_tools: if functional_tool.on_tool_stock_num == 0: @@ -327,7 +338,6 @@ class CAMWorkOrderProgramKnifePlan(models.Model): 'name': cnc_processing.workorder_id.production_id.name, 'cam_procedure_code': cnc_processing.program_name, 'filename': cnc_processing.cnc_id.name, - 'functional_tool_type_id': cnc_processing.functional_tool_type_id.id, 'functional_tool_name': cnc_processing.cutting_tool_name, 'cam_cutter_spacing_code': cnc_processing.cutting_tool_no, 'process_type': cnc_processing.processing_type, @@ -338,8 +348,11 @@ class CAMWorkOrderProgramKnifePlan(models.Model): '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用刀需求!!!') class FunctionalToolAssembly(models.Model): diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py index df9a341e..8098c5a1 100644 --- a/sf_tool_management/models/mrp_workorder.py +++ b/sf_tool_management/models/mrp_workorder.py @@ -36,6 +36,7 @@ class CNCprocessing(models.Model): obj = super(CNCprocessing, self).create(vals) # 调用CAM工单程序用刀计划创建方法 self.env['sf.cam.work.order.program.knife.plan'].create_cam_work_plan(obj) + logging.info('成功调用CAM工单程序用刀计划创建方法!!!') return obj diff --git a/sf_warehouse/__init__.py b/sf_warehouse/__init__.py index c081ee06..c9ba0265 100644 --- a/sf_warehouse/__init__.py +++ b/sf_warehouse/__init__.py @@ -1,2 +1,3 @@ # -*-coding:utf-8-*- from . import models +from . import wizard diff --git a/sf_warehouse/__manifest__.py b/sf_warehouse/__manifest__.py index 04051b06..b409c7ce 100644 --- a/sf_warehouse/__manifest__.py +++ b/sf_warehouse/__manifest__.py @@ -15,6 +15,7 @@ 'data/ir_cron_data.xml', 'security/sf_stock_security.xml', 'security/ir.model.access.csv', + 'wizard/wizard_view.xml', 'views/view.xml', 'views/shelf_location.xml', 'views/change_stock_move_views.xml', diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index b4bec292..50469284 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -191,6 +191,7 @@ class SfLocation(models.Model): # return res # 生成货位 + def create_location(self): """ 当仓库类型为货架时,自动生成其下面的货位,数量为货架层数*层数容量 @@ -429,7 +430,6 @@ class ShelfLocation(models.Model): } return action - # # 仓库类别(selection:库区、库位、货位) # location_type = fields.Selection([ # ('货架', '货架'), @@ -516,6 +516,19 @@ class ShelfLocation(models.Model): else: raise UserError("该库位无产品") + @api.model_create_multi + def create(self, vals_list): + # 编码重复校验 + barcode_list = [] + for val in vals_list: + location = self.search([('barcode', '=', val['barcode'])]) + if location: + barcode_list.append(val['name']) + if barcode_list: + raise UserError("货位编码【%s】存在重复" % barcode_list) + records = super(ShelfLocation, self).create(vals_list) + return records + class Sf_stock_move_line(models.Model): _name = 'stock.move.line' @@ -531,7 +544,7 @@ class Sf_stock_move_line(models.Model): current_product_id = fields.Integer(compute='_compute_location_dest_id_value', store=True) there_is_no_sn = fields.Boolean('是否有序列号', default=False) - rfid = fields.Char('Rfid', readonly=True) + rfid = fields.Char('Rfid') rfid_barcode = fields.Char('Rfid', compute='_compute_rfid') @api.depends('lot_id') @@ -812,35 +825,39 @@ class Sf_stock_move_line(models.Model): destination_location_id = fields.Many2one( 'sf.shelf.location', string='目标货位') - @api.onchange('destination_location_id') - def _compute_destination_location_id(self): + def compute_destination_location_id(self): for record in self: + obj = self.env['sf.shelf.location'].search([('name', '=', + self.destination_location_id.name)]) if record.lot_id: shelf_location_obj = self.env['sf.shelf.location'].search( [('product_sn_id', '=', record.lot_id.id)]) if shelf_location_obj: shelf_location_obj.product_sn_id = False - # obj = self.env['sf.shelf.location'].search([('location_id', '=', - # self.destination_location_id.id)]) - obj = self.env['sf.shelf.location'].search([('name', '=', - self.destination_location_id.name)]) if obj: obj.product_sn_id = record.lot_id.id - else: - pass else: - obj = self.env['sf.shelf.location'].search([('name', '=', - self.destination_location_id.name)]) if obj: obj.product_sn_id = record.lot_id.id else: - obj = self.env['sf.shelf.location'].search([('name', '=', - self.destination_location_id.name)]) if obj: obj.product_id = record.product_id.id # obj.location_status = '占用' obj.product_num += record.reserved_uom_qty + @api.onchange('destination_location_id') + def _check_destination_location_id(self): + for item in self: + if item: + i = 0 + barcode = item.destination_location_id.barcode + for line in item.picking_id.move_line_ids_without_package: + if barcode and barcode == line.destination_location_id.barcode: + i += 1 + if i > 1: + raise ValidationError( + '【%s】货位已经被占用,请重新选择!!!' % item.destination_location_id.barcode) + class SfStockPicking(models.Model): _inherit = 'stock.picking' @@ -863,12 +880,15 @@ class SfStockPicking(models.Model): res = super(SfStockPicking, self).button_validate() for line in self.move_line_ids: if line: + # 调用入库方法进行入库 + line.compute_destination_location_id() if line.current_location_id: if line.current_location_id.product_sn_id: line.current_location_id.product_sn_id = False # line.current_location_id.location_status = '空闲' line.current_location_id.product_num = 0 + # 对入库作业的刀柄和托盘进行Rfid绑定校验 for move in self.move_ids: if move and move.product_id.cutting_tool_material_id.name == '刀柄' or '托盘' in ( move.product_id.fixture_material_id.name or ''): diff --git a/sf_warehouse/security/ir.model.access.csv b/sf_warehouse/security/ir.model.access.csv index db246adc..a5b3b2fa 100644 --- a/sf_warehouse/security/ir.model.access.csv +++ b/sf_warehouse/security/ir.model.access.csv @@ -132,6 +132,9 @@ access_sf_cutting_tool_material_group_sf_stock_manager,sf_cutting_tool_material_ access_sf_cutting_tool_standard_library_group_sf_stock_manager,sf_cutting_tool_standard_library_group_sf_stock_manager,sf_base.model_sf_cutting_tool_standard_library,sf_warehouse.group_sf_stock_manager,1,0,1,0 access_sf_tool_materials_basic_parameters_group_sf_stock_manager,sf_tool_materials_basic_parameters_group_sf_stock_manager,sf_base.model_sf_tool_materials_basic_parameters,sf_warehouse.group_sf_stock_manager,1,0,1,0 +access_sf_shelf_location_wizard_group_plan_dispatch,sf_shelf_location_wizard_group_plan_dispatch,model_sf_shelf_location_wizard,sf_base.group_plan_dispatch,1,0,0,0 +access_sf_shelf_location_wizard_group_sf_stock_user_group_sf_stock_user,sf_shelf_location_wizard_group_sf_stock_user_group_sf_stock_user,model_sf_shelf_location_wizard,sf_warehouse.group_sf_stock_user,1,0,0,0 +access_sf_shelf_location_wizard_group_sf_stock_manager,sf_shelf_location_wizard_group_sf_stock_manager,model_sf_shelf_location_wizard,sf_warehouse.group_sf_stock_manager,1,1,1,0 diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml index 7af154b7..519eca85 100644 --- a/sf_warehouse/views/change_stock_move_views.xml +++ b/sf_warehouse/views/change_stock_move_views.xml @@ -19,7 +19,7 @@ + '=', there_is_no_sn)]" options="{'no_create': True,'no_create_edit':True}"/> diff --git a/sf_warehouse/views/shelf_location.xml b/sf_warehouse/views/shelf_location.xml index d736f89c..a0e1a5c1 100644 --- a/sf_warehouse/views/shelf_location.xml +++ b/sf_warehouse/views/shelf_location.xml @@ -126,9 +126,19 @@ Shelf Location form sf.shelf.location - + - + - - - - - + + + + + @@ -175,7 +185,7 @@ shelf.location.kanban sf.shelf.location - + + + + 货位变更 + sf.shelf.location.wizard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 货位变更 + ir.actions.act_window + sf.shelf.location.wizard + form + + new + + \ No newline at end of file