[MERGE] forward port branch saas-6 up to 88802b066c
This commit is contained in:
@@ -3,4 +3,11 @@ xset s off
|
||||
xset -dpms
|
||||
|
||||
export HOME=/tmp
|
||||
/usr/bin/firefox http://localhost:8069/point_of_sale/display &
|
||||
|
||||
DISPLAY_URL='http://localhost:8069/point_of_sale/display'
|
||||
|
||||
# wait until odoo is ready, otherwise you will have to plug a
|
||||
# keyboard into the posbox just to refresh firefox
|
||||
until wget -q "${DISPLAY_URL}" -O /dev/null ; do sleep 1 ; done
|
||||
|
||||
/usr/bin/firefox "${DISPLAY_URL}" &
|
||||
|
||||
+47
-18
@@ -3267,35 +3267,64 @@ class stock_inventory_line(osv.osv):
|
||||
res['value']['product_qty'] = th_qty
|
||||
return res
|
||||
|
||||
def _resolve_inventory_line(self, cr, uid, inventory_line, context=None):
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
quant_obj = self.pool.get('stock.quant')
|
||||
diff = inventory_line.theoretical_qty - inventory_line.product_qty
|
||||
if not diff:
|
||||
return
|
||||
#each theorical_lines where difference between theoretical and checked quantities is not 0 is a line for which we need to create a stock move
|
||||
vals = {
|
||||
# Do not forward port in 10.0 and beyond
|
||||
def _get_move_values(self, cr, uid, inventory_line, qty, location_id, location_dest_id):
|
||||
return {
|
||||
'name': _('INV:') + (inventory_line.inventory_id.name or ''),
|
||||
'product_id': inventory_line.product_id.id,
|
||||
'product_uom': inventory_line.product_uom_id.id,
|
||||
'product_uom_qty': qty,
|
||||
'date': inventory_line.inventory_id.date,
|
||||
'company_id': inventory_line.inventory_id.company_id.id,
|
||||
'inventory_id': inventory_line.inventory_id.id,
|
||||
'state': 'confirmed',
|
||||
'restrict_lot_id': inventory_line.prod_lot_id.id,
|
||||
'restrict_partner_id': inventory_line.partner_id.id,
|
||||
}
|
||||
'location_id': location_id,
|
||||
'location_dest_id': location_dest_id,
|
||||
}
|
||||
|
||||
def _fixup_negative_quants(self, cr, uid, inventory_line):
|
||||
""" This will handle the irreconciable quants created by a force availability followed by a
|
||||
return. When generating the moves of an inventory line, we look for quants of this line's
|
||||
product created to compensate a force availability. If there are some and if the quant
|
||||
which it is propagated from is still in the same location, we move it to the inventory
|
||||
adjustment location before getting it back. Getting the quantity from the inventory
|
||||
location will allow the negative quant to be compensated.
|
||||
"""
|
||||
quant_obj = self.pool.get('stock.quant')
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
quant_ids = self._get_quants(cr, uid, inventory_line)
|
||||
for quant in quant_obj.browse(cr, uid, quant_ids).filtered(lambda q: q.propagated_from_id.location_id.id == inventory_line.location_id.id):
|
||||
# send the quantity to the inventory adjustment location
|
||||
move_out_vals = self._get_move_values(cr, uid, inventory_line, quant.qty, inventory_line.location_id.id, inventory_line.product_id.property_stock_inventory.id)
|
||||
move_out = stock_move_obj.create(cr, uid, move_out_vals)
|
||||
move_out = stock_move_obj.browse(cr, uid, [move_out])
|
||||
quant_obj.quants_reserve(cr, uid, [(quant, quant.qty)], move_out)
|
||||
move_out.action_done()
|
||||
|
||||
# get back the quantity from the inventory adjustment location
|
||||
move_in_vals = self._get_move_values(cr, uid, inventory_line, quant.qty, inventory_line.product_id.property_stock_inventory.id, inventory_line.location_id.id)
|
||||
move_in = stock_move_obj.create(cr, uid, move_in_vals)
|
||||
move_in = stock_move_obj.browse(cr, uid, [move_in])
|
||||
move_in.action_done()
|
||||
|
||||
def _resolve_inventory_line(self, cr, uid, inventory_line, context=None):
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
quant_obj = self.pool.get('stock.quant')
|
||||
self._fixup_negative_quants(cr, uid, inventory_line)
|
||||
|
||||
if float_compare(inventory_line.theoretical_qty, inventory_line.product_qty, precision_rounding=inventory_line.product_id.uom_id.rounding) == 0:
|
||||
return False
|
||||
diff = inventory_line.theoretical_qty - inventory_line.product_qty
|
||||
|
||||
#each theorical_lines where difference between theoretical and checked quantities is not 0 is a line for which we need to create a stock move
|
||||
inventory_location_id = inventory_line.product_id.property_stock_inventory.id
|
||||
if diff < 0:
|
||||
#found more than expected
|
||||
vals['location_id'] = inventory_location_id
|
||||
vals['location_dest_id'] = inventory_line.location_id.id
|
||||
vals['product_uom_qty'] = -diff
|
||||
if diff < 0: # found more than expected
|
||||
vals = self._get_move_values(cr, uid, inventory_line, abs(diff), inventory_location_id, inventory_line.location_id.id)
|
||||
else:
|
||||
#found less than expected
|
||||
vals['location_id'] = inventory_line.location_id.id
|
||||
vals['location_dest_id'] = inventory_location_id
|
||||
vals['product_uom_qty'] = diff
|
||||
vals = self._get_move_values(cr, uid, inventory_line, abs(diff), inventory_line.location_id.id, inventory_location_id)
|
||||
|
||||
move_id = stock_move_obj.create(cr, uid, vals, context=context)
|
||||
move = stock_move_obj.browse(cr, uid, move_id, context=context)
|
||||
if diff > 0:
|
||||
|
||||
@@ -1494,3 +1494,133 @@ class TestStockFlow(TestStockCommon):
|
||||
# We should also make sure that when matching stock moves with pack operations, it takes the correct
|
||||
self.assertEqual(len(picking_out.move_lines[0].linked_move_operation_ids), 2, 'We should only have 2 links beween the move and the 2 operations')
|
||||
self.assertEqual(len(picking_out.move_lines[0].quant_ids), 2, 'We should have exactly 2 quants in the end')
|
||||
|
||||
# Do not forward port in 10.0 and beyond
|
||||
def test_inventory_adjustment_and_negative_quants_1(self):
|
||||
"""Make sure negative quants from returns get wiped out with an inventory adjustment"""
|
||||
productA = self.env['product.product'].create({'name': 'Product A', 'type': 'product'})
|
||||
stock_location = self.env.ref('stock.stock_location_stock')
|
||||
customer_location = self.env.ref('stock.stock_location_customers')
|
||||
location_loss = self.env.ref('stock.location_inventory')
|
||||
|
||||
# Create a picking out and force availability
|
||||
picking_out = self.env['stock.picking'].create({
|
||||
'partner_id': self.env.ref('base.res_partner_2').id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
||||
'location_id': stock_location.id,
|
||||
'location_dest_id': customer_location.id,
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': productA.name,
|
||||
'product_id': productA.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': productA.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': stock_location.id,
|
||||
'location_dest_id': customer_location.id,
|
||||
})
|
||||
picking_out.action_confirm()
|
||||
picking_out.force_assign()
|
||||
picking_out.do_transfer()
|
||||
|
||||
# Create return picking for all goods
|
||||
default_data = self.env['stock.return.picking']\
|
||||
.with_context(active_ids=picking_out.ids, active_id=picking_out.ids[0])\
|
||||
.default_get([
|
||||
'move_dest_exists',
|
||||
'product_return_moves'
|
||||
])
|
||||
|
||||
list_return_moves = default_data['product_return_moves']
|
||||
default_data['product_return_moves'] = [(0, 0, return_move) for return_move in list_return_moves]
|
||||
|
||||
return_wiz = self.env['stock.return.picking']\
|
||||
.with_context(active_ids=picking_out.ids, active_id=picking_out.ids[0])\
|
||||
.create(default_data)
|
||||
res = return_wiz._create_returns()[0]
|
||||
return_pick = self.env['stock.picking'].browse(res)
|
||||
return_pick.action_assign()
|
||||
return_pick.do_transfer()
|
||||
|
||||
# Make an inventory adjustment to set the quantity to 0
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'Starting for product_1',
|
||||
'filter': 'product',
|
||||
'location_id': stock_location.id,
|
||||
'product_id': productA.id,
|
||||
})
|
||||
inventory.prepare_inventory()
|
||||
self.assertEqual(len(inventory.line_ids), 1, "Wrong inventory lines generated.")
|
||||
self.assertEqual(inventory.line_ids.theoretical_qty, 0, "Theoretical quantity should be zero.")
|
||||
inventory.action_done()
|
||||
|
||||
# The inventory adjustment should have created two moves
|
||||
self.assertEqual(len(inventory.move_ids), 2)
|
||||
quantity = inventory.move_ids.mapped('product_qty')
|
||||
self.assertEqual(quantity, [1, 1], "Moves created with wrong quantity.")
|
||||
location_ids = inventory.move_ids.mapped('location_id').ids
|
||||
self.assertEqual(set(location_ids), {stock_location.id, location_loss.id})
|
||||
|
||||
# There should be no quant in the stock location
|
||||
quants = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
|
||||
self.assertEqual(len(quants), 0)
|
||||
|
||||
# There should be one quant in the inventory loss location
|
||||
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', location_loss.id)])
|
||||
self.assertEqual(len(quant), 1)
|
||||
self.assertEqual(quant.qty, 1)
|
||||
|
||||
def test_inventory_adjustment_and_negative_quants_2(self):
|
||||
"""Make sure negative quants get wiped out with an inventory adjustment"""
|
||||
productA = self.env['product.product'].create({'name': 'Product A', 'type': 'product'})
|
||||
stock_location = self.env.ref('stock.stock_location_stock')
|
||||
customer_location = self.env.ref('stock.stock_location_customers')
|
||||
location_loss = self.env.ref('stock.location_inventory')
|
||||
|
||||
# Create a picking out and force availability
|
||||
picking_out = self.env['stock.picking'].create({
|
||||
'partner_id': self.env.ref('base.res_partner_2').id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
||||
'location_id': stock_location.id,
|
||||
'location_dest_id': customer_location.id,
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': productA.name,
|
||||
'product_id': productA.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': productA.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': stock_location.id,
|
||||
'location_dest_id': customer_location.id,
|
||||
})
|
||||
picking_out.action_confirm()
|
||||
picking_out.force_assign()
|
||||
picking_out.do_transfer()
|
||||
|
||||
# Make an inventory adjustment to set the quantity to 0
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'Starting for product_1',
|
||||
'filter': 'product',
|
||||
'location_id': stock_location.id,
|
||||
'product_id': productA.id,
|
||||
})
|
||||
inventory.prepare_inventory()
|
||||
self.assertEqual(len(inventory.line_ids), 1, "Wrong inventory lines generated.")
|
||||
self.assertEqual(inventory.line_ids.theoretical_qty, -1, "Theoretical quantity should be -1.")
|
||||
inventory.line_ids.product_qty = 0 # Put the quantity back to 0
|
||||
inventory.action_done()
|
||||
|
||||
# The inventory adjustment should have created one
|
||||
self.assertEqual(len(inventory.move_ids), 1)
|
||||
quantity = inventory.move_ids.mapped('product_qty')
|
||||
self.assertEqual(quantity, [1], "Moves created with wrong quantity.")
|
||||
location_ids = inventory.move_ids.mapped('location_id').ids
|
||||
self.assertEqual(set(location_ids), {location_loss.id})
|
||||
|
||||
# There should be no quant in the stock location
|
||||
quants = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
|
||||
self.assertEqual(len(quants), 0)
|
||||
|
||||
# There should be no quant in the inventory loss location
|
||||
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', location_loss.id)])
|
||||
self.assertEqual(len(quant), 0)
|
||||
|
||||
Reference in New Issue
Block a user