diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 6ce80937..ac17af6a 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -112,6 +112,8 @@ + + diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index fb458f28..1edf529d 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -69,6 +69,50 @@ class ResMrpWorkOrder(models.Model): delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效', tracking=True) + back_button_display = fields.Boolean(default=False, compute='_compute_back_button_display', store=True) + + @api.depends('state') + def _compute_back_button_display(self): + for record in self: + sorted_workorders = record.production_id.workorder_ids.filtered(lambda w: w.state != 'cancel').sorted( + key=lambda w: w.sequence) + if not sorted_workorders: + continue + position = next((idx for idx, workorder in enumerate(sorted_workorders) if workorder.id == record.id), -1) + cur_workorder = sorted_workorders[position] + if position == len(sorted_workorders) - 1: + picking_ids = cur_workorder.production_id.sale_order_id.picking_ids + finished_product_area = picking_ids.filtered( + lambda picking: picking.location_dest_id.name == '成品存货区' and picking.state == 'done' + ) + if finished_product_area: + moves = self.env['stock.move'].search([ + ('name', '=', cur_workorder.production_id.name), + ('state', '!=', 'cancel') + ]) + finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None) + if not finish_move and not cur_workorder.is_subcontract: + record.back_button_display = True + else: + record.back_button_display = any( + finish_move.move_dest_ids.ids not in move.ids and record.state == 'done' + for picking in finished_product_area + for move in picking.move_ids + ) + else: + if record.state == 'done': + record.back_button_display = True + else: + record.back_button_display = False + else: + next_workorder = sorted_workorders[position + 1] + next_state = next_workorder.state + if ((next_state == 'ready' and not next_workorder.is_subcontract) or (next_workorder.state == 'pending' and next_workorder.is_subcontract)) and cur_workorder.state == 'done': + record.back_button_display = True + else: + record.back_button_display = False + if cur_workorder.is_subcontract: + record.back_button_display = False date_planned_start = fields.Datetime(tracking=True) @api.depends('processing_panel') @@ -86,6 +130,84 @@ class ResMrpWorkOrder(models.Model): manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True) + def button_back(self): + if self.production_id.state == 'rework': + raise UserError('制造订单为返工时不能进行工单回退') + sorted_workorders = self.production_id.workorder_ids.filtered(lambda w: w.state != 'cancel').sorted( + key=lambda w: w.sequence) + position = next((idx for idx, workorder in enumerate(sorted_workorders) if workorder.id == self.id), -1) + cur_workorder = sorted_workorders[position] + if position == len(sorted_workorders) - 1: + # 末工序 + picking_ids = cur_workorder.production_id.sale_order_id.picking_ids + finished_product_area = picking_ids.filtered( + lambda picking: picking.location_dest_id.name == '成品存货区' and picking.state == 'done' + ) + moves = self.env['stock.move'].search([ + ('name', '=', cur_workorder.production_id.name), + ('state', '!=', 'cancel') + ]) + finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None) or [] + if any( + finish_move.move_dest_ids.ids in move.ids + for picking in finished_product_area + for move in picking.move_ids + ): + raise UserError('已入库,无法回退') + else: + move_finished = cur_workorder.production_id.move_finished_ids + random_element = random.choice(move_finished) + moves = self.env['stock.move'].search([ + ('name', '=', random_element.name), + ('state', '!=', 'cancel') + ]) + move_lines = self.env['stock.move.line'].search([ + ('reference', '=', random_element.name), + ('state', '!=', 'cancel') + ]) + moves.state = 'assigned' + external_assistance = move_lines.filtered( + lambda picking: picking.location_id.name != '外协线边仓' + ) + external_assistance.state = 'assigned' + # move_lines.state = 'assigned' + self.time_ids.date_end = None + cur_workorder.state = 'progress' + cur_workorder.production_id.state = 'progress' + quality_check = self.env['quality.check'].search( + [('workorder_id', '=', self.id)]) + for check_order in quality_check: + if check_order.point_id.is_inspect: + check_order.state = 'waiting' + else: + check_order.state = 'none' + # move_dest_ids + finished_quants = moves.mapped('move_line_ids.lot_id.quant_ids') + finished_quants.quantity = 0 + finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None) + finish_move.move_dest_ids.reserved_availability = 0 + finish_move.move_dest_ids.move_line_ids.state = 'draft' + finish_move.move_dest_ids.move_line_ids.unlink() + # finish_move.move_dest_ids.move_line_ids.reserved_uom_qty = 0 + else: + next_workorder = sorted_workorders[position + 1] + next_state = next_workorder.state + if next_state not in ['pending', 'waiting', 'ready']: + raise UserError('下工序已经开始,无法回退') + if next_workorder.is_subcontract: + next_workorder.picking_ids.write({'state': 'waiting'}) + next_workorder.state = 'pending' + self.time_ids.date_end = None + cur_workorder.state = 'progress' + cur_workorder.production_id.state = 'progress' + quality_check = self.env['quality.check'].search( + [('workorder_id', '=', self.id)]) + for check_order in quality_check: + if check_order.point_id.is_inspect: + check_order.state = 'waiting' + else: + check_order.state = 'none' + def _compute_working_users(self): super()._compute_working_users() for item in self: diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 419eec50..dab95f1b 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -48,6 +48,7 @@ + @@ -58,6 +59,10 @@ {'invisible': [('state', '!=', 'ready')]} + + +