'warehouse_selectable': fields.boolean('Applicable on Warehouse'),
'supplied_wh_id': fields.many2one('stock.warehouse', 'Supplied Warehouse'),
'supplier_wh_id': fields.many2one('stock.warehouse', 'Supplier Warehouse'),
+ 'company_id': fields.many2one('res.company', 'Company', select=1, help='Let this field empty if this route is shared between all companies'),
}
_defaults = {
'sequence': lambda self, cr, uid, ctx: 0,
'active': True,
'product_selectable': True,
+ 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.location.route', context=c),
}
'''
domain += location and [('location_id', 'child_of', location.id)] or []
domain += [('product_id', '=', product.id)] + domain
+ #don't take into account location that are production, supplier or inventory
+ ignore_location_ids = self.pool.get('stock.location').search(cr, uid, [('usage', 'in', ('production', 'supplier', 'inventory'))], context=context)
+ domain.append(('location_id','not in',ignore_location_ids))
res = []
offset = 0
while quantity > 0:
return True
def cancel_assign(self, cr, uid, ids, context=None):
- """ Cancels picking and moves.
+ """ Cancels picking for the moves that are in the assigned state
@return: True
"""
for pick in self.browse(cr, uid, ids, context=context):
- move_ids = [x.id for x in pick.move_lines]
+ move_ids = [x.id for x in pick.move_lines if x not in ['done', 'cancel']]
self.pool.get('stock.move').cancel_assign(cr, uid, move_ids, context=context)
return True
('name_ref_uniq', 'unique (name, ref)', 'The combination of Serial Number and internal reference must be unique !'),
]
+ def action_traceability(self, cr, uid, ids, context=None):
+ """ It traces the information of lots
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: List of IDs selected
+ @param context: A standard dictionary
+ @return: A dictionary of values
+ """
+ quant_obj = self.pool.get("stock.quant")
+ move_obj = self.pool.get("stock.move")
+ quants = quant_obj.search(cr, uid, [('lot_id', 'in', ids)], context=context)
+ moves = set()
+ for quant in quant_obj.browse(cr, uid, quants, context=context):
+ moves |= {move.id for move in quant.history_ids}
+ if moves:
+ return {
+ 'domain': "[('id','in',["+','.join(map(str, list(moves)))+"])]",
+ 'name': _('Traceability'),
+ 'view_mode': 'tree,form',
+ 'view_type': 'form',
+ 'context': {'tree_view_ref': 'stock.view_move_tree'},
+ 'res_model': 'stock.move',
+ 'type': 'ir.actions.act_window',
+ }
+ return False
+
+
# ----------------------------------------------------
# Move
if qty > 0:
self.check_tracking(cr, uid, move, move.restrict_lot_id.id, context=context)
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain, prefered_domain=prefered_domain, fallback_domain=fallback_domain, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)
- quant_obj.quants_move(cr, uid, quants, move, context=context)
+ quant_obj.quants_move(cr, uid, quants, move, lot_id=move.restrict_lot_id.id, owner_id=move.restrict_partner_id.id, context=context)
#unreserve the quants and make them available for other operations/moves
quant_obj.quants_unreserve(cr, uid, move, context=context)
raise osv.except_osv(_('User Error!'), _('You can only delete draft moves.'))
return super(stock_move, self).unlink(cr, uid, ids, context=context)
- def action_scrap(self, cr, uid, ids, quantity, location_id, restrict_lot_id=False, context=None):
+ def action_scrap(self, cr, uid, ids, quantity, location_id, restrict_lot_id=False, restrict_partner_id=False, context=None):
""" Move the scrap/damaged product into scrap location
@param cr: the database cursor
@param uid: the user id
'scrapped': True,
'location_dest_id': location_id,
'restrict_lot_id': restrict_lot_id,
+ 'restrict_partner_id': restrict_partner_id,
}
new_move = self.copy(cr, uid, move.id, default_val)
self.action_done(cr, uid, res, context=context)
return res
- def action_consume(self, cr, uid, ids, quantity, location_id=False, restrict_lot_id=False, context=None):
+ def action_consume(self, cr, uid, ids, quantity, location_id=False, restrict_lot_id=False, restrict_partner_id=False, context=None):
""" Consumed product with specific quantity from specific source location. This correspond to a split of the move (or write if the quantity to consume is >= than the quantity of the move) followed by an action_done
@param ids: ids of stock move object to be consumed
@param quantity : specify consume quantity (given in move UoM)
ctx = context.copy()
if location_id:
ctx['source_location_id'] = location_id
- res.append(self.split(cr, uid, move, move_qty - quantity_rest, restrict_lot_id=restrict_lot_id, context=ctx))
+ res.append(self.split(cr, uid, move, move_qty - quantity_rest, restrict_lot_id=restrict_lot_id,
+ restrict_partner_id=restrict_partner_id, context=ctx))
else:
res.append(move.id)
if location_id:
- self.write(cr, uid, [move.id], {'location_id': location_id, 'restrict_lot_id': restrict_lot_id}, context=context)
+ self.write(cr, uid, [move.id], {'location_id': location_id, 'restrict_lot_id': restrict_lot_id,
+ 'restrict_partner_id': restrict_partner_id}, context=context)
self.action_done(cr, uid, res, context=context)
return res
- def split(self, cr, uid, move, qty, restrict_lot_id=False, context=None):
+ def split(self, cr, uid, move, qty, restrict_lot_id=False, restrict_partner_id=False, context=None):
""" Splits qty from move move into a new move
:param move: browse record
:param qty: float. quantity to split (given in product UoM)
'move_dest_id': False,
'reserved_quant_ids': [],
'restrict_lot_id': restrict_lot_id,
+ 'restrict_partner_id': restrict_partner_id
}
if context.get('source_location_id'):
defaults['location_id'] = context['source_location_id']
:rtype: list of tuple
"""
#default available choices
- res_filter = [('none', ' All products of a whole location'), ('product', 'One product only')]
+ res_filter = [('none', _('All products of a whole location')), ('product', _('One product only'))]
settings_obj = self.pool.get('stock.config.settings')
config_ids = settings_obj.search(cr, uid, [], limit=1, order='id DESC', context=context)
#If we don't have updated config until now, all fields are by default false and so should be not dipslayed
if stock_settings.group_stock_tracking_owner:
res_filter.append(('owner', _('One owner only')))
res_filter.append(('product_owner', _('One product for a specific owner')))
- if stock_settings.group_stock_production_lot:
- res_filter.append(('lot', _('One Lot/Serial Number')))
if stock_settings.group_stock_tracking_lot:
+ res_filter.append(('lot', _('One Lot/Serial Number')))
+ if stock_settings.group_stock_packaging:
res_filter.append(('pack', _('A Pack')))
return res_filter
_name = "stock.inventory.line"
_description = "Inventory Line"
_rec_name = "inventory_id"
+ _order = "inventory_id, location_name, product_code, product_name, prod_lot_id"
+
+ def _get_product_name_change(self, cr, uid, ids, context=None):
+ return self.pool.get('stock.inventory.line').search(cr, uid, [('product_id', 'in', ids)], context=context)
+
+ def _get_location_change(self, cr, uid, ids, context=None):
+ return self.pool.get('stock.inventory.line').search(cr, uid, [('location_id', 'in', ids)], context=context)
+
_columns = {
'inventory_id': fields.many2one('stock.inventory', 'Inventory', ondelete='cascade', select=True),
'location_id': fields.many2one('stock.location', 'Location', required=True, select=True),
'state': fields.related('inventory_id', 'state', type='char', string='Status', readonly=True),
'th_qty': fields.float('Theoretical Quantity', readonly=True),
'partner_id': fields.many2one('res.partner', 'Owner'),
+ 'product_name': fields.related('product_id', 'name', type='char', string='Product name', store={
+ 'product.product': (_get_product_name_change, ['name', 'default_code'], 20),
+ 'stock.inventory.line': (lambda self, cr, uid, ids, c={}: ids, ['product_id'], 20),}),
+ 'product_code': fields.related('product_id', 'default_code', type='char', string='Product code', store={
+ 'product.product': (_get_product_name_change, ['name', 'default_code'], 20),
+ 'stock.inventory.line': (lambda self, cr, uid, ids, c={}: ids, ['product_id'], 20),}),
+ 'location_name': fields.related('location_id', 'complete_name', type='char', string='Location name', store={
+ 'stock.location': (_get_location_change, ['name', 'location_id', 'active'], 20),
+ 'stock.inventory.line': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 20),}),
}
_defaults = {
vals[values['field']] = location_id
#create new sequences
- in_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence in'), 'prefix': vals.get('code', '') + '\IN\\', 'padding': 5}, context=context)
- out_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence out'), 'prefix': vals.get('code', '') + '\OUT\\', 'padding': 5}, context=context)
- pack_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence packing'), 'prefix': vals.get('code', '') + '\PACK\\', 'padding': 5}, context=context)
- pick_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence picking'), 'prefix': vals.get('code', '') + '\PICK\\', 'padding': 5}, context=context)
- int_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence internal'), 'prefix': vals.get('code', '') + '\INT\\', 'padding': 5}, context=context)
+ in_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence in'), 'prefix': vals.get('code', '') + '/IN/', 'padding': 5}, context=context)
+ out_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence out'), 'prefix': vals.get('code', '') + '/OUT/', 'padding': 5}, context=context)
+ pack_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence packing'), 'prefix': vals.get('code', '') + '/PACK/', 'padding': 5}, context=context)
+ pick_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence picking'), 'prefix': vals.get('code', '') + '/PICK/', 'padding': 5}, context=context)
+ int_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence internal'), 'prefix': vals.get('code', '') + '/INT/', 'padding': 5}, context=context)
#create WH
new_id = super(stock_warehouse, self).create(cr, uid, vals=vals, context=context)
'warehouse_id': new_id,
'code': 'outgoing',
'sequence_id': out_seq_id,
+ 'return_picking_type_id': in_type_id,
'default_location_src_id': output_loc.id,
'default_location_dest_id': customer_loc.id,
'sequence': max_sequence + 4,
'color': color}, context=context)
+ picking_type_obj.write(cr, uid, [in_type_id], {'return_picking_type_id': out_type_id}, context=context)
int_type_id = picking_type_obj.create(cr, uid, vals={
'name': _('Internal Transfers'),
'warehouse_id': new_id,