[ADD] Add removal and putaway strategies
bzr revid: jco@openerp.com-20130624152850-7y0t36wcj2hyba4o
This commit is contained in:
parent
a0edfd14e8
commit
c45c32a164
|
@ -1,3 +1,8 @@
|
|||
-
|
||||
Set product category removal strategy as LIFO
|
||||
-
|
||||
!record {model:product.category, id: product.product_category_1}:
|
||||
removal_strategy: lifo
|
||||
-
|
||||
Set a product as using lifo price
|
||||
-
|
||||
|
|
|
@ -574,6 +574,7 @@ class product_category(osv.osv):
|
|||
|
||||
_inherit = 'product.category'
|
||||
_columns = {
|
||||
'removal_strategy': fields.selection([('fifo', 'FIFO'), ('lifo', 'LIFO'), ('nearest', 'Nearest Location')], "Picking Strategy"),
|
||||
'property_stock_journal': fields.property(
|
||||
relation='account.journal',
|
||||
type='many2one',
|
||||
|
|
|
@ -342,6 +342,10 @@ class stock_location(osv.osv):
|
|||
'location': ids
|
||||
})
|
||||
return product_obj.get_product_available(cr, uid, product_ids, context=context)
|
||||
|
||||
def get_removal_strategy(self, cr, uid, id, product_id, context=None):
|
||||
product = self.pool.get("product.product").browse(cr, uid, product_id, context=context)
|
||||
return product.categ_id.removal_strategy or 'fifo'
|
||||
|
||||
def _product_get(self, cr, uid, id, product_ids=False, context=None, states=None):
|
||||
"""
|
||||
|
@ -534,7 +538,6 @@ class stock_quant(osv.osv):
|
|||
self.write(cr, uid, quant.id, {'qty': new_qty}, context=context)
|
||||
quants_to_reserve.append(new_quant)
|
||||
self.write(cr, uid, quants_to_reserve, {'reservation_id': move.id}, context=context)
|
||||
print "Assign", quants_to_reserve, "to",
|
||||
self.pool.get("stock.move").write(cr, uid, [move.id], {'reserved_quant_ids': [(4, x) for x in quants_to_reserve]}, context=context)
|
||||
|
||||
|
||||
|
@ -679,6 +682,9 @@ class stock_quant(osv.osv):
|
|||
'history_ids': [(4, move.id)]}, context=context)
|
||||
return self.filter_quants_with_out_history(cr, uid, quants_rec, context=context)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def choose_quants(self, cr, uid, location_id, product_id, qty, context=None):
|
||||
"""
|
||||
|
@ -691,8 +697,12 @@ class stock_quant(osv.osv):
|
|||
"""
|
||||
#TODO Normally, you should check the removal strategy now
|
||||
#But we will assume it is FIFO for the moment
|
||||
possible_quants = self.search(cr, uid, [('location_id', 'child_of', location_id), ('product_id','=',product_id),
|
||||
('qty', '>', 0.0), ('reservation_id', '=', False)], order = 'in_date, id', context=context)
|
||||
if self.pool.get('stock.location').get_removal_strategy(cr, uid, location_id, product_id, context=context) == 'lifo':
|
||||
possible_quants = self.search(cr, uid, [('location_id', 'child_of', location_id), ('product_id','=',product_id),
|
||||
('qty', '>', 0.0), ('reservation_id', '=', False)], order = 'in_date desc, id desc', context=context)
|
||||
else:
|
||||
possible_quants = self.search(cr, uid, [('location_id', 'child_of', location_id), ('product_id','=',product_id),
|
||||
('qty', '>', 0.0), ('reservation_id', '=', False)], order = 'in_date, id', context=context)
|
||||
qty_todo = qty
|
||||
res = []
|
||||
for quant in self.browse(cr, uid, possible_quants, context=context):
|
||||
|
@ -2357,7 +2367,7 @@ class stock_move(osv.osv):
|
|||
return True
|
||||
|
||||
#
|
||||
# Duplicate stock.move
|
||||
# Duplicate stock.move -> no duplicate: assign quants
|
||||
#
|
||||
def check_assign(self, cr, uid, ids, context=None):
|
||||
""" Checks the product type and accordingly writes the state.
|
||||
|
@ -2383,9 +2393,6 @@ class stock_move(osv.osv):
|
|||
#Convert UoM qty -> check rounding now in product_reserver
|
||||
qty = uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, move.product_id.uom_id.id)
|
||||
res2 = quant_obj.choose_quants(cr, uid, move.location_id.id, move.product_id.id, qty, context=context)
|
||||
#ASSUME: it is on the same location anyways -> when putaway works: can not be all the time
|
||||
|
||||
|
||||
#Should group quants by location:
|
||||
quants = {}
|
||||
qtys = {}
|
||||
|
@ -2399,7 +2406,7 @@ class stock_move(osv.osv):
|
|||
quants[quant.location_id.id] += [quant.id]
|
||||
qtys[quant.location_id.id] += [tuple[1]]
|
||||
qty[quant.location_id.id] += tuple[1]
|
||||
|
||||
|
||||
res = [(qty[key], key) for key in quants.keys()]
|
||||
if res:
|
||||
#_product_available_test depends on the next status for correct functioning
|
||||
|
@ -2418,7 +2425,7 @@ class stock_move(osv.osv):
|
|||
r = res.pop(0)
|
||||
move_id = self.copy(cr, uid, move.id, {'product_uos_qty': product_uos_qty, 'product_qty': r[0], 'location_id': r[1]})
|
||||
done.append(move_id)
|
||||
quant_obj.split_and_assign_quants(cr, uid, zip(quants[r[1]], qtys[r[1]]), self.browse(cr, uid, move_id, context=context), context=context)
|
||||
|
||||
if done:
|
||||
count += len(done)
|
||||
self.write(cr, uid, done, {'state': 'assigned'})
|
||||
|
@ -2713,7 +2720,7 @@ class stock_move(osv.osv):
|
|||
quants = {}
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
quants[move.id] = []
|
||||
if (move.location_id.usage in ['supplier']):
|
||||
if (move.location_id.usage in ['supplier', 'inventory']):
|
||||
#Create quants
|
||||
reconciled_quants = self.pool.get("stock.quant").create_quants(cr, uid, move, context=context)
|
||||
quants[move.id] += reconciled_quants
|
||||
|
@ -2722,7 +2729,6 @@ class stock_move(osv.osv):
|
|||
self.check_total_qty(cr, uid, ids, context=context)
|
||||
reconciled_quants = self.pool.get("stock.quant").move_quants(cr, uid, quants[move.id], move, context=context)
|
||||
quants[move.id] += reconciled_quants
|
||||
print "Reconciled quants", quants[move.id]
|
||||
#Generate negative quants if necessary
|
||||
|
||||
|
||||
|
|
|
@ -85,6 +85,46 @@ class product_pulled_flow(osv.osv):
|
|||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'product.pulled.flow', context=c),
|
||||
}
|
||||
|
||||
|
||||
class product_putaway_strategy(osv.osv):
|
||||
|
||||
def _calc_product_ids(self, cr, uid, ids, field, arg, context=None):
|
||||
'''
|
||||
This function should check on which products (including if the products are in a product category) this putaway strategy is used
|
||||
'''
|
||||
pass
|
||||
|
||||
_name = 'product.putaway'
|
||||
_description = 'Put Away Strategy'
|
||||
_columns = {
|
||||
'product_ids':fields.function(_calc_product_ids, "Products"),
|
||||
'product_categ_id':fields.many2one('product.category', 'Product Category'),
|
||||
'location_id': fields.many2one('stock.location','Parent Location', help="Parent Destination Location from which a child bin location needs to be chosen"), #domain=[('type', '=', 'parent')],
|
||||
'method': fields.selection([('nearest_empty','Nearest Empty Location'), ('add_or_nearest_empty', 'Try to add on another location, otherwise nearest empty'), ('L2R', 'left to right'), ('R2L', 'right to left'),
|
||||
('high2low', 'high to low'), ('low2high', 'low to high'), ('fixed', 'Fixed Location')], "Method"),
|
||||
}
|
||||
|
||||
|
||||
class product_removal_strategy(osv.osv):
|
||||
|
||||
def _calc_product_ids(self, cr, uid, ids, field, arg, context=None):
|
||||
'''
|
||||
This function should check on which products (including if the products are in a product category) this removal strategy is used
|
||||
'''
|
||||
pass
|
||||
|
||||
_name = 'product.removal'
|
||||
_description = 'Removal Strategy'
|
||||
_columns = {
|
||||
'product_ids':fields.function(_calc_product_ids, "Products"),
|
||||
'product_categ_id':fields.many2one('product.category', 'Product Category'),
|
||||
'location_id': fields.many2one('stock.location', 'Parent Location', help="Parent Source Location from which a child bin location needs to be chosen"), #, domain=[('type', '=', 'parent')]
|
||||
'method': fields.selection([('fifo', 'FIFO'), ('lifo', 'LIFO'), ('nearest', 'Nearest location')], "Method"),
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = 'product.product'
|
||||
_columns = {
|
||||
|
@ -98,6 +138,15 @@ class product_product(osv.osv):
|
|||
|
||||
|
||||
|
||||
class product_category(osv.osv):
|
||||
_inherit = 'product.category'
|
||||
_columns = {
|
||||
#'route_ids': fields.many2many('stock.route', 'product_catg_id', 'route_id', 'Routes'),
|
||||
'removal_strategy_ids': fields.many2many('product.removal', 'product_catg_id', 'removal_strat_id' 'Removal Strategies'),
|
||||
'putaway_strategy_ids': fields.many2many('product.putaway', 'product_catg_id', 'putaway_strat_id', 'Put Away Strategies'),
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class stock_move(osv.osv):
|
||||
|
@ -119,6 +168,26 @@ class stock_move(osv.osv):
|
|||
|
||||
class stock_location(osv.osv):
|
||||
_inherit = 'stock.location'
|
||||
_columns = {
|
||||
'removal_strategy_ids': fields.many2many('product.removal', 'location_id', 'removal_strat_id' 'Removal Strategies'),
|
||||
'putaway_strategy_ids': fields.many2many('product.putaway', 'location_id', 'putaway_strat_id', 'Put Away Strategies'),
|
||||
}
|
||||
|
||||
|
||||
def get_putaway_strategy(self, cr, uid, id, product_id, context=None):
|
||||
product = self.pool.get("product.product").browse(cr, uid, product_id, context=context)
|
||||
strats = self.pool.get('product.removal').search(cr, uid, [('location_id','=',id), ('product_categ_id','child_of', product.categ_id.id)], context=context) #Also child_of for location???
|
||||
return strats and strats[0] or 'nearest'
|
||||
|
||||
def get_removal_strategy(self, cr, uid, id, product_id, context=None):
|
||||
product = self.pool.get("product.product").browse(cr, uid, product_id, context=context)
|
||||
strats = self.pool.get('product.removal').search(cr, uid, [('location_id','=',id), ('product_categ_id','child_of', product.categ_id.id)], context=context) #Also child_of for location???
|
||||
if not strats:
|
||||
strat = product.categ_id.removal_strategy
|
||||
else:
|
||||
strat = strats[0]
|
||||
return strat or product.categ_id.removal_strategy or 'fifo'
|
||||
|
||||
def chained_location_get(self, cr, uid, location, partner=None, product=None, context=None):
|
||||
if product:
|
||||
for path in product.path_ids:
|
||||
|
|
Loading…
Reference in New Issue