# -*- coding: utf-8 -*- import re from odoo import api, fields, models, _ class MrpProduction(models.Model): _inherit = 'mrp.production' _description = "制造订单" _order = 'create_date desc' # tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘") maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests") request_ids = fields.One2many('maintenance.request', 'production_id') model_file = fields.Binary('模型文件', related='product_id.model_file') schedule_state = fields.Selection([('未排', '未排'), ('已排', '已排')], string='排程状态', default='未排') @api.depends('request_ids') def _compute_maintenance_count(self): for production in self: production.maintenance_count = len(production.request_ids) # 维修模块按钮 def button_maintenance_req(self): self.ensure_one() return { 'name': _('New Maintenance Request'), 'view_mode': 'form', 'res_model': 'maintenance.request', 'type': 'ir.actions.act_window', 'context': { 'default_company_id': self.company_id.id, 'default_production_id': self.id, }, 'domain': [('production_id', '=', self.id)], } # 打开维修模块请求 def open_maintenance_request_mo(self): self.ensure_one() action = { 'name': _('Maintenance Requests'), 'view_mode': 'kanban,tree,form,pivot,graph,calendar', 'res_model': 'maintenance.request', 'type': 'ir.actions.act_window', 'context': { 'default_company_id': self.company_id.id, 'default_production_id': self.id, }, 'domain': [('production_id', '=', self.id)], } if self.maintenance_count == 1: production = self.env['maintenance.request'].search([('production_id', '=', self.id)]) action['view_mode'] = 'form' action['res_id'] = production.id return action def action_generate_serial(self): self.ensure_one() iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[ 'ir.sequence'].next_by_code('stock.lot.serial') iot_code_name = re.sub('[\u4e00-\u9fa5]', "", iot_code) self.lot_producing_id = self.env['stock.lot'].create({ 'product_id': self.product_id.id, 'company_id': self.company_id.id, 'name': iot_code_name, }) if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids: self.move_finished_ids.filtered( lambda m: m.product_id == self.product_id).move_line_ids.lot_id = self.lot_producing_id if self.product_id.tracking == 'serial': self._set_qty_producing() # 重载根据工序生成工单的程序:如果产品BOM中没有工序时, # 根据产品对应的模板类型中工序,去生成工单; # CNC加工工序的选取规则: # 如果自动报价有带过来预分配的机床, # 则根据设备找到工作中心;否则采用前面描述的工作中心分配机制; # 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心; def _create_workorder3(self): for production in self: if not production.bom_id or not production.product_id: continue workorders_values = [] product_qty = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) exploded_boms, dummy = production.bom_id.explode(production.product_id, product_qty / production.bom_id.product_qty, picking_type=production.bom_id.picking_type_id) for bom, bom_data in exploded_boms: # If the operations of the parent BoM and phantom BoM are the same, don't recreate work orders. if not (bom.operation_ids and (not bom_data['parent_line'] or bom_data[ 'parent_line'].bom_id.operation_ids != bom.operation_ids)): continue for operation in bom.operation_ids: if operation._skip_operation_line(bom_data['product']): continue workorders_values += [{ 'name': operation.name, 'production_id': production.id, 'workcenter_id': operation.workcenter_id.id, 'product_uom_id': production.product_uom_id.id, 'operation_id': operation.id, 'state': 'pending', }] if production.product_id.categ_id.type == '成品': # 根据加工面板的面数及对应的工序模板生成工单 i = 0 processing_panel_len = len(production.product_id.model_processing_panel.split(',')) for k in (production.product_id.model_processing_panel.split(',')): product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search( [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], order='sequence asc' ) i += 1 for route in product_routing_workcenter: if i == 1 and route.routing_type == '获取CNC加工程序': workorders_values.append( self.env['mrp.workorder'].json_workorder_str('', production, route)) if route.is_repeat == True: workorders_values.append( self.env['mrp.workorder'].json_workorder_str(k, production, route)) if i == processing_panel_len and route.routing_type == '解除装夹': workorders_values.append( self.env['mrp.workorder'].json_workorder_str(k, production, route)) # 表面工艺工序 # 获取表面工艺id if production.product_id.model_process_parameters_ids: surface_technics_arr = [] # 工序id route_workcenter_arr = [] for item in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids: surface_technics_arr.append(item.route_workcenter_id.surface_technics_id.id) route_workcenter_arr.append(item.route_workcenter_id.id) if surface_technics_arr: production_process_category = self.env['sf.production.process.category'].search( [('production_process_ids.id', 'in', surface_technics_arr)], order='sequence asc' ) # 用filter刷选表面工艺id'是否存在工艺类别对象里 if production_process_category: for p in production_process_category: production_process = p.production_process_ids.filtered( lambda pp: pp.id in surface_technics_arr) if production_process: process_parameter = production.product_id.model_process_parameters_ids.filtered( lambda pm: pm.process_id.id == production_process.id) if process_parameter: # 产品为表面工艺服务的供应商 product_production_process = self.env['product.template'].search( [('server_product_process_parameters_id', '=', process_parameter.id)]) if product_production_process: route_production_process = self.env[ 'mrp.routing.workcenter'].search( [('surface_technics_id', '=', production_process.id), ('id', 'in', route_workcenter_arr)]) if route_production_process: workorders_values.append( self.env[ 'mrp.workorder']._json_workorder_surface_process_str( production, route_production_process, process_parameter, product_production_process.seller_ids[0].partner_id.id)) elif production.product_id.categ_id.type == '坯料': embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search( [('embryo_model_type_id', '=', production.product_id.embryo_model_type_id.id)], order='sequence asc' ) for route in embryo_routing_workcenter: workorders_values.append( self.env['mrp.workorder'].json_workorder_str('', production, route)) production.workorder_ids = workorders_values process_parameter_workorder = self.env['mrp.workorder'].search( [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id), ('is_subcontract', '=', True)]) if process_parameter_workorder: is_pick = False consecutive_workorders = [] m = 0 sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id) for i in range(len(sorted_workorders) - 1): if m == 0: is_pick = False if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \ sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \ sorted_workorders[i].id == sorted_workorders[i + 1].id - 1: if sorted_workorders[i] not in consecutive_workorders: consecutive_workorders.append(sorted_workorders[i]) consecutive_workorders.append(sorted_workorders[i + 1]) m += 1 continue else: if m == len(consecutive_workorders) - 1 and m != 0: self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) if sorted_workorders[i] in consecutive_workorders: is_pick = True consecutive_workorders = [] m = 0 # 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单 if is_pick is False: self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production) if m == len(consecutive_workorders) - 1 and m != 0: self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) if sorted_workorders[i] in consecutive_workorders: is_pick = True consecutive_workorders = [] m = 0 if m == len(consecutive_workorders) - 1 and m != 0: self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) if is_pick is False and m == 0: if len(sorted_workorders) == 1: self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production) else: self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production) for workorder in production.workorder_ids: workorder.duration_expected = workorder._get_duration_expected() # 在之前的销售单上重新生成制造订单 def create_production1_values(self, production): production_values_str = {'origin': production.origin, 'product_id': production.product_id.id, 'product_description_variants': production.product_description_variants, 'product_qty': production.product_qty, 'product_uom_id': production.product_uom_id.id, 'location_src_id': production.location_src_id.id, 'location_dest_id': production.location_dest_id.id, 'bom_id': production.bom_id.id, 'date_deadline': production.date_deadline, 'date_planned_start': production.date_planned_start, 'date_planned_finished': production.date_planned_finished, 'procurement_group_id': False, 'propagate_cancel': production.propagate_cancel, 'orderpoint_id': production.orderpoint_id.id, 'picking_type_id': production.picking_type_id.id, 'company_id': production.company_id.id, 'move_dest_ids': production.move_dest_ids.ids, 'user_id': production.user_id.id} return production_values_str def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id): move_values = { 'name': item.name if item.name else '/', 'company_id': item.company_id.id, 'product_id': item.bom_id.bom_line_ids.product_id.id, 'product_uom': item.bom_id.bom_line_ids.product_uom_id.id, 'product_uom_qty': 1.0, 'location_id': location_src_id, 'location_dest_id': location_dest_id, 'origin': item.origin, 'picking_type_id': picking_type_id, } return move_values # 工单排序 def _reset_work_order_sequence1(self, k): sequen = 0 for rec in self: current_sequence = 10 for work in rec.workorder_ids: work.sequence = current_sequence current_sequence += 10 if work.name == '后置三元质量检测' and work.processing_panel == k: sequen = work.sequence for work in rec.workorder_ids: if work.name == '后置三元质量检测(返工)' and work.processing_panel == k: work.sequence = sequen + 2 if work.name == 'CNC加工(返工)' and work.processing_panel == k: work.sequence = sequen + 1 # 在制造订单上新增工单 def _create_workorder1(self, k): for production in self: if not production.bom_id or not production.product_id: continue workorders_values = [] product_qty = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) exploded_boms, dummy = production.bom_id.explode(production.product_id, product_qty / production.bom_id.product_qty, picking_type=production.bom_id.picking_type_id) for bom, bom_data in exploded_boms: # If the operations of the parent BoM and phantom BoM are the same, don't recreate work orders. if not (bom.operation_ids and (not bom_data['parent_line'] or bom_data[ 'parent_line'].bom_id.operation_ids != bom.operation_ids)): continue for operation in bom.operation_ids: if operation._skip_operation_line(bom_data['product']): continue workorders_values += [{ 'name': operation.name, 'production_id': production.id, 'workcenter_id': operation.workcenter_id.id, 'product_uom_id': production.product_uom_id.id, 'operation_id': operation.id, 'state': 'pending', }] # 根据加工面板的面数及对应的成品工序模板生成工单 i = 0 production.product_id.model_processing_panel = k for k in (production.product_id.model_processing_panel.split(',')): routingworkcenter = self.env['sf.product.model.type.routing.sort'].search( [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], order='sequence asc' ) i += 1 for route in routingworkcenter: if route.routing_type == '后置三元质量检测': workorders_values.append( self.env['mrp.workorder'].json_workorder_str1(k, production, route) ) if route.routing_type == 'CNC加工': workorders_values.append( self.env['mrp.workorder'].json_workorder_str1(k, production, route)) production.workorder_ids = workorders_values workorder = self.env['mrp.workorder'].browse(production.workorder_ids.ids) print(workorder) # for item in workorder: # workorder.duration_expected = workorder._get_duration_expected() def _create_workorder2(self, k): self._create_workorder1(k) self._reset_work_order_sequence1(k) return True def _reset_work_order_sequence(self): for rec in self: current_sequence = 1 for work in rec.workorder_ids: work.sequence = current_sequence current_sequence += 1 if work.name == '获取CNC加工程序': work.button_start() #work.fetchCNC() # 创建工单并进行排序 def _create_workorder(self): self._create_workorder3() self._reset_work_order_sequence() return True