def action_explode(self): """ Explodes pickings """ # in order to explode a move, we must have a picking_type_id on that move because otherwise the move # won't be assigned to a picking and it would be weird to explode a move into several if they aren't # all grouped in the same picking. moves_ids_to_return = OrderedSet() moves_ids_to_unlink = OrderedSet() phantom_moves_vals_list = [] for move in self: if not move.picking_type_id or (move.production_id and move.production_id.product_id == move.product_id): moves_ids_to_return.add(move.id) continue bom = self.env['mrp.bom'].sudo()._bom_find(product=move.product_id, company_id=move.company_id.id, bom_type='phantom') if not bom: moves_ids_to_return.add(move.id) continue if move.picking_id.immediate_transfer: factor = move.product_uom._compute_quantity(move.quantity_done, bom.product_uom_id) / bom.product_qty else: factor = move.product_uom._compute_quantity(move.product_uom_qty, bom.product_uom_id) / bom.product_qty boms, lines = bom.sudo().explode(move.product_id, factor, picking_type=bom.picking_type_id) for bom_line, line_data in lines: if move.picking_id.immediate_transfer: phantom_moves_vals_list += move._generate_move_phantom(bom_line, 0, line_data['qty']) else: phantom_moves_vals_list += move._generate_move_phantom(bom_line, line_data['qty'], 0) # delete the move with original product which is not relevant anymore moves_ids_to_unlink.add(move.id) self.env['stock.move'].browse(moves_ids_to_unlink).sudo().unlink() if phantom_moves_vals_list: phantom_moves = self.env['stock.move'].create(phantom_moves_vals_list) phantom_moves._adjust_procure_method() moves_ids_to_return |= phantom_moves.action_explode().ids return self.env['stock.move'].browse(moves_ids_to_return)
def descendants(self, model_names, *kinds): """ Return the models corresponding to ``model_names`` and all those that inherit/inherits from them. """ assert all(kind in ('_inherit', '_inherits') for kind in kinds) funcs = [attrgetter(kind + '_children') for kind in kinds] models = OrderedSet() queue = deque(model_names) while queue: model = self[queue.popleft()] models.add(model._name) for func in funcs: queue.extend(func(model)) return models
def __call__(self, path=None, path_args=None, **kw): path = path or self.path for key, value in self.args.items(): kw.setdefault(key, value) path_args = OrderedSet(path_args or []) | self.path_args paths, fragments = {}, [] for key, value in kw.items(): if value and key in path_args: if isinstance(value, models.BaseModel): paths[key] = slug(value) else: paths[key] = u"%s" % value elif value: if isinstance(value, list) or isinstance(value, set): fragments.append( werkzeug.url_encode([(key, item) for item in value])) else: fragments.append(werkzeug.url_encode([(key, value)])) for key in path_args: value = paths.get(key) if value is not None: path += '/' + key + '/' + value if fragments: path += '?' + '&'.join(fragments) return path
def _get_in_move_lines(self): """ Returns the `stock.move.line` records of `self` considered as incoming. It is done thanks to the `_should_be_valued` method of their source and destionation location as well as their owner. :returns: a subset of `self` containing the incoming records :rtype: recordset """ self.ensure_one() res = OrderedSet() for move_line in self.move_line_ids: if move_line.owner_id and move_line.owner_id != move_line.company_id.partner_id: continue if not move_line.location_id._should_be_valued( ) and move_line.location_dest_id._should_be_valued(): res.add(move_line.id) return self.env['stock.move.line'].browse(res)
def __init__(self, path='', path_args=None, **args): self.path = path self.args = args self.path_args = OrderedSet(path_args or [])