def action_cancel(self): consume_moves = self.env['stock.move'].search([ ('id', 'in', self.ids), ('raw_material_production_id', '!=', False) ]) if self.env.context.get('forbid_unreserve_quants') and consume_moves: new_target_qty = self.env.context.get('new_target_qty', False) reserved_quant = self.env['stock.quant'].search( [('reservation_id', 'in', consume_moves.ids)], limit=1) reserved_qty = sum([ sum([quant.qty for quant in move.reserved_quant_ids]) for move in reserved_quant.reservation_id. raw_material_production_id.move_lines if move.product_id == reserved_quant.product_id ]) qty_to_unreserve = new_target_qty and reserved_qty - new_target_qty or reserved_qty if reserved_quant and float_compare( reserved_qty, 0, precision_rounding=reserved_quant.product_id.uom_id. rounding) > 0: raise exceptions.except_orm( t(u"Error!"), t(u"Product %s in MO %s: forbidden to cancel a move with reserved quants " u"(quantity to unreserve: %s %s)") % (reserved_quant.product_id.display_name, reserved_quant. reservation_id.raw_material_production_id.display_name, qty_to_unreserve, reserved_quant.product_id.uom_id.display_name)) return super(UpdateChangeStockMove, self).action_cancel()
def change_prod_qty(self): for rec in self: if self.env.context.get('active_id'): order = self.env['mrp.production'].browse( self.env.context.get('active_id')) # Raise if MO is linked to a procurement, in order not to allow a difference between procurement and # its origin moves (which are production moves of the MO) if order.procurement_id: raise ForbiddenChangeQtyMO( order.id, t(u"%s: impossible to change the quantity of a manufacturing order " u"created by Odoo. Please create an extra manufacturing order or " u"make stock scheduler cancel this one.") % order.display_name) # Check raw material moves if order.bom_id and float_compare( order.product_qty, rec.product_qty, precision_rounding=order.product_id.uom_id.rounding ) != 0: order.product_qty = rec.product_qty order.update_prod_after_change_qty() # Check production moves if order.move_prod_id: order.move_prod_id.write( {'product_uom_qty': rec.product_qty}) self._update_product_to_produce(order, rec.product_qty)
def _update_product_to_produce(self, prod, qty): """ Take into account the already created products to update the products tu create when changing the product quantity in OFs. """ qty_done = 0.0 for done_product in prod.move_created_ids2: if done_product.product_id.id == prod.product_id.id: qty_done += done_product.product_uom_qty qty -= qty_done if qty < 0.0: raise exceptions.except_orm( t(u"Error!"), t(u" You have already produced %s %s of the product : %s.") % (qty_done, prod.product_uom.name, prod.product_id.name)) return super(UpdateChangeProductionQty, self)._update_product_to_produce(prod, qty)
def update_moves(self): for mrp in self: post = '' changes_to_do = [] done_products = [] needed_new_moves = [] useless_moves = self.env['stock.move'] wrong_location_moves = self.env['stock.move'] needed_products = [x.product_id for x in mrp.product_lines] source_location = mrp.get_actual_location_src_and_routing()[0] for move in mrp.move_lines: if move.product_id not in needed_products: useless_moves |= move if move.location_id != source_location: wrong_location_moves |= move if useless_moves: for product in list(set([x.product_id for x in useless_moves])): post += t("Product %s: not needed anymore<br>") % ( product.display_name) useless_moves.with_context( cancel_procurement=True, forbid_unreserve_quants=True).action_cancel() if wrong_location_moves: for product in list( set([x.product_id for x in wrong_location_moves])): post += t("Product %s: raw material move had wrong source location, it was cancelled<br>") % \ (product.display_name) wrong_location_moves.with_context( cancel_procurement=True, forbid_unreserve_quants=True).action_cancel() for item in mrp.move_lines: if not item.product_id in done_products: if not self.env.context.get('ignore_done_moves'): total_done_moves =\ sum([x.product_qty for x in mrp.move_lines2 if x.product_id == item.product_id and x.state == 'done' and x.location_dest_id.usage == 'production']) else: total_done_moves = 0 total_old_need = sum([ x.product_qty for x in mrp.move_lines if x.product_id == item.product_id ]) total_new_need = 0 for product_line in mrp.product_lines: if product_line.product_id == item.product_id: total_new_need += self.env[ 'product.uom']._compute_qty_obj( from_unit=product_line.product_uom, qty=product_line.product_qty, to_unit=product_line.product_id.uom_id) prec = item.product_id.uom_id.rounding if float_compare(total_new_need, total_done_moves, precision_rounding=prec) < 0: raise exceptions.except_orm( t(u"Error!"), t(u"Product %s on MO %s : %s %s where consumed, impossible to " u"decrease this quantity to %s") % (item.product_id.display_name, mrp.name, total_done_moves, item.product_id.uom_id.display_name, total_new_need)) total_old_need += total_done_moves if float_compare(total_new_need, total_old_need, precision_rounding=prec) != 0 \ and float_compare(total_new_need, 0, precision_rounding=prec) != 0: changes_to_do += [(item.product_id, total_new_need, total_old_need, total_done_moves)] done_products += [item.product_id] for product, total_new_need, total_old_need, total_done_moves in changes_to_do: qty = total_new_need - total_old_need if float_compare(qty, 0, precision_rounding=prec) > 0: move = mrp._make_consume_line_from_data( mrp, product, product.uom_id.id, qty, False, 0) self.env['stock.move'].browse(move).action_confirm() else: final_running_qty = total_new_need - total_done_moves moves = self.env['stock.move'].search( [('raw_material_production_id', '=', mrp.id), ('state', 'not in', ['done', 'cancel']), ('product_id', '=', product.id)], order='product_qty desc, id asc') qty_ordered = sum([x.product_qty for x in moves]) while float_compare( qty_ordered, final_running_qty, precision_rounding=product.uom_id.rounding) > 0: moves[0].with_context( cancel_procurement=True, forbid_unreserve_quants=True, new_target_qty=final_running_qty).action_cancel() qty_ordered -= moves[0].product_qty moves -= moves[0] if float_compare( qty_ordered, final_running_qty, precision_rounding=product.uom_id.rounding) < 0: move = self._make_consume_line_from_data( mrp, product, product.uom_id.id, final_running_qty - qty_ordered, False, 0) self.env['stock.move'].browse(move).action_confirm() post += t("Product %s: quantity changed from %s to %s<br>") % \ (product.display_name, total_old_need, total_new_need) for item in mrp.product_lines: if item.product_id not in [ y.product_id for y in mrp.move_lines if y.state != 'cancel' ]: needed_new_moves += [item] post += t("Raw material move created of quantity %s for product %s<br>") % \ (item.product_qty, item.product_id.display_name) product_qtys = {} if self.env.context.get('force_production_qty'): needed_products, _ = self.env['mrp.bom']._bom_explode( mrp.bom_id, mrp.product_id, self.env.context.get('force_production_qty')) product_qtys = { products['product_id']: products['product_qty'] for products in needed_products } for item in needed_new_moves: product = item.product_id if not product_qtys: to_consume_qty = item.product_qty else: to_consume_qty = product_qtys[product.id] move_id = mrp._make_consume_line_from_data( mrp, product, item.product_uom.id, to_consume_qty, False, 0) self.env['stock.move'].browse(move_id).action_confirm() if post: mrp.message_post(post)