[REF] *{stock,mrp}*: rename reserved fields

This commit rename product_uom_qty into reserved_uom_qty and product_qty
into reserved_qty on stock move line to stop mistake them with the stock
move quantities fields.

Task: 2648449
Part-of: odoo/odoo#80434
This commit is contained in:
William Henrotin
2021-12-07 16:20:06 +00:00
parent cd9833e4ad
commit 56e7bcf0cb
42 changed files with 248 additions and 248 deletions
@@ -56,7 +56,7 @@ class ChooseDeliveryPackage(models.TransientModel):
and not ml.result_package_id
)
if not move_line_ids:
move_line_ids = picking_move_lines.filtered(lambda ml: float_compare(ml.product_uom_qty, 0.0,
move_line_ids = picking_move_lines.filtered(lambda ml: float_compare(ml.reserved_uom_qty, 0.0,
precision_rounding=ml.product_uom_id.rounding) > 0 and float_compare(ml.qty_done, 0.0,
precision_rounding=ml.product_uom_id.rounding) == 0)
+6 -6
View File
@@ -1513,7 +1513,7 @@ class MrpProduction(models.Model):
# Remove the serial move line without reserved quantity. Post inventory will assigned all the non done moves
# So those move lines are duplicated.
backorders.move_raw_ids.move_line_ids.filtered(lambda ml: ml.product_id.tracking == 'serial' and ml.product_qty == 0).unlink()
backorders.move_raw_ids.move_line_ids.filtered(lambda ml: ml.product_id.tracking == 'serial' and ml.reserved_qty == 0).unlink()
for old_wo, wo in zip(self.workorder_ids, backorders.workorder_ids):
wo.qty_produced = max(old_wo.qty_produced - old_wo.qty_producing, 0)
@@ -1921,19 +1921,19 @@ class MrpProduction(models.Model):
new_moves_vals.append(move_vals[0])
new_moves_quantity_to_split.append(uom_qty_to_split)
elif move.raw_material_production_id:
move.move_line_ids.product_uom_qty = 0
move.move_line_ids[0].product_uom_qty = move.product_uom_qty
move.move_line_ids.reserved_uom_qty = 0
move.move_line_ids[0].reserved_uom_qty = move.product_uom_qty
if backorder:
new_moves = self.env['stock.move'].create(new_moves_vals)
for move, quantity_to_split, new_move in zip(new_moves_origin, new_moves_quantity_to_split, new_moves):
if move.raw_material_production_id:
move.move_line_ids[0].copy({
'move_id': new_move.id,
'product_uom_qty': quantity_to_split,
'reserved_uom_qty': quantity_to_split,
'lot_id': move.move_line_ids[0].lot_id.id if move.move_line_ids[0].lot_id else 0,
})
move.with_context(bypass_reservation_update=True).move_line_ids.product_uom_qty = 0
move.with_context(bypass_reservation_update=True).move_line_ids[0].product_uom_qty = move.product_uom_qty
move.with_context(bypass_reservation_update=True).move_line_ids.reserved_uom_qty = 0
move.with_context(bypass_reservation_update=True).move_line_ids[0].reserved_uom_qty = move.product_uom_qty
for old_wo, wo in zip(production.workorder_ids, backorder.workorder_ids):
wo.qty_produced = max(old_wo.qty_produced - old_wo.qty_producing, 0)
wo.qty_producing = 1
+2 -2
View File
@@ -788,7 +788,7 @@ class MrpWorkorder(models.Model):
if move_line:
if self.product_id.tracking == 'serial':
raise UserError(_('You cannot produce the same serial number twice.'))
move_line.product_uom_qty += self.qty_producing
move_line.reserved_uom_qty += self.qty_producing
move_line.qty_done += self.qty_producing
else:
quantity = self.product_uom_id._compute_quantity(self.qty_producing, self.product_id.uom_id, rounding_method='HALF-UP')
@@ -797,7 +797,7 @@ class MrpWorkorder(models.Model):
'move_id': production_move.id,
'product_id': production_move.product_id.id,
'lot_id': self.finished_lot_id.id,
'product_uom_qty': self.qty_producing,
'reserved_uom_qty': self.qty_producing,
'product_uom_id': self.product_uom_id.id,
'qty_done': self.qty_producing,
'location_id': production_move.location_id.id,
+1 -1
View File
@@ -70,7 +70,7 @@ class StockMoveLine(models.Model):
def _reservation_is_updatable(self, quantity, reserved_quant):
self.ensure_one()
if self.produce_line_ids.lot_id:
ml_remaining_qty = self.qty_done - self.product_uom_qty
ml_remaining_qty = self.qty_done - self.reserved_uom_qty
ml_remaining_qty = self.product_uom_id._compute_quantity(ml_remaining_qty, self.product_id.uom_id, rounding_method="HALF-UP")
if float_compare(ml_remaining_qty, quantity, precision_rounding=self.product_id.uom_id.rounding) < 0:
return False
@@ -119,7 +119,7 @@
<t t-set="move_lines" t-value="move.move_line_ids.filtered(lambda x: x.state == 'done' and x.qty_done)"/>
</t>
<t t-else="">
<t t-set="move_lines" t-value="move.move_line_ids.filtered(lambda x: x.state != 'done' and x.product_qty)"/>
<t t-set="move_lines" t-value="move.move_line_ids.filtered(lambda x: x.state != 'done' and x.reserved_qty)"/>
</t>
<t t-foreach="move_lines" t-as="move_line">
<t t-if="move_line.product_uom_id.category_id == uom_categ_unit">
@@ -142,7 +142,7 @@
<span t-field="move_line.product_uom_id" groups="uom.group_uom"/>
</t>
<t t-else="">
<span t-esc="move_line.product_uom_qty" t-if="move_line.state !='done'"/>
<span t-esc="move_line.reserved_uom_qty" t-if="move_line.state !='done'"/>
<span t-esc="move_line.qty_done" t-if="move_line.state =='done'"/>
<span t-field="move_line.product_uom_id" groups="uom.group_uom"/>
</t>
+5 -5
View File
@@ -599,7 +599,7 @@ class TestMrpOrder(TestMrpCommon):
# p2
details_operation_form = Form(mo.move_raw_ids[0], view=self.env.ref('stock.view_stock_move_operations'))
with details_operation_form.move_line_ids.edit(0) as line:
line.qty_done = line.product_uom_qty
line.qty_done = line.reserved_uom_qty
with details_operation_form.move_line_ids.new() as line:
line.qty_done = 1
details_operation_form.save()
@@ -609,7 +609,7 @@ class TestMrpOrder(TestMrpCommon):
for i in range(len(details_operation_form.move_line_ids)):
# reservation in shelf1: 3 lot1, shelf2: 3 lot1, stock: 4 lot2
with details_operation_form.move_line_ids.edit(i) as line:
line.qty_done = line.product_uom_qty
line.qty_done = line.reserved_uom_qty
with details_operation_form.move_line_ids.new() as line:
line.qty_done = 2
line.lot_id = first_lot_for_p1
@@ -619,7 +619,7 @@ class TestMrpOrder(TestMrpCommon):
details_operation_form.save()
move_1 = mo.move_raw_ids.filtered(lambda m: m.product_id == p1)
# qty_done/product_uom_qty lot
# qty_done/reserved_uom_qty lot
# 3/3 lot 1 shelf 1
# 1/1 lot 1 shelf 2
# 2/2 lot 1 shelf 2
@@ -666,7 +666,7 @@ class TestMrpOrder(TestMrpCommon):
self.assertEqual(len(ml_p1), 2)
self.assertEqual(sorted(ml_p1.mapped('qty_done')), [2.0, 3.0], 'Quantity done should be 1.0, 2.0 or 3.0')
self.assertEqual(m_p1.quantity_done, 5.0, 'Total qty done should be 6.0')
self.assertEqual(sum(ml_p1.mapped('product_uom_qty')), 5.0, 'Total qty reserved should be 5.0')
self.assertEqual(sum(ml_p1.mapped('reserved_uom_qty')), 5.0, 'Total qty reserved should be 5.0')
mo.button_mark_done()
self.assertEqual(mo.state, 'done', "Production order should be in done state.")
@@ -707,7 +707,7 @@ class TestMrpOrder(TestMrpCommon):
mo.button_mark_done()
self.assertTrue(all(s == 'done' for s in mo.move_raw_ids.mapped('state')))
self.assertEqual(sum(mo.move_raw_ids.mapped('move_line_ids.product_uom_qty')), 0)
self.assertEqual(sum(mo.move_raw_ids.mapped('move_line_ids.reserved_uom_qty')), 0)
def test_consumption_strict_1(self):
""" Checks the constraints of a strict BOM without tracking when playing around
+3 -3
View File
@@ -383,11 +383,11 @@ class TestUnbuild(TestMrpCommon):
mo = mo_form.save()
details_operation_form = Form(mo.move_raw_ids.filtered(lambda ml: ml.product_id == p2), view=self.env.ref('stock.view_stock_move_operations'))
with details_operation_form.move_line_ids.edit(0) as ml:
ml.qty_done = ml.product_uom_qty
ml.qty_done = ml.reserved_uom_qty
with details_operation_form.move_line_ids.edit(1) as ml:
ml.qty_done = ml.product_uom_qty
ml.qty_done = ml.reserved_uom_qty
with details_operation_form.move_line_ids.edit(2) as ml:
ml.qty_done = ml.product_uom_qty
ml.qty_done = ml.reserved_uom_qty
details_operation_form.save()
mo.button_mark_done()
+2 -2
View File
@@ -265,7 +265,7 @@
<field name="qty_done" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="product_uom_id" invisible="1"/>
<field name="product_uom_qty" invisible="1"/>
<field name="reserved_uom_qty" invisible="1"/>
<field name="state" invisible="1"/>
<field name="move_id" invisible="1"/>
<field name="id" invisible="1"/>
@@ -347,7 +347,7 @@
<field name="qty_done" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="product_uom_id" invisible="1"/>
<field name="product_uom_qty" invisible="1"/>
<field name="reserved_uom_qty" invisible="1"/>
<field name="state" invisible="1"/>
<field name="move_id" invisible="1"/>
<field name="id" invisible="1"/>
@@ -61,8 +61,8 @@ class MrpImmediateProduction(models.TransientModel):
for move in production.move_raw_ids.filtered(lambda m: m.state not in ['done', 'cancel']):
rounding = move.product_uom.rounding
for move_line in move.move_line_ids:
if move_line.product_uom_qty:
move_line.qty_done = min(move_line.product_uom_qty, move_line.move_id.should_consume_qty)
if move_line.reserved_uom_qty:
move_line.qty_done = min(move_line.reserved_uom_qty, move_line.move_id.should_consume_qty)
if float_compare(move.quantity_done, move.should_consume_qty, precision_rounding=rounding) >= 0:
break
if float_compare(move.product_uom_qty, move.quantity_done, precision_rounding=move.product_uom.rounding) == 1:
@@ -89,27 +89,27 @@ class MrpProduction(models.Model):
rounding = ml.product_uom_id.rounding
if float_compare(quantity, 0, precision_rounding=rounding) <= 0:
break
quantity_to_process = min(quantity, ml.product_uom_qty - ml.qty_done)
quantity_to_process = min(quantity, ml.reserved_uom_qty - ml.qty_done)
quantity -= quantity_to_process
new_quantity_done = (ml.qty_done + quantity_to_process)
# on which lot of finished product
if float_compare(new_quantity_done, ml.product_uom_qty, precision_rounding=rounding) >= 0:
if float_compare(new_quantity_done, ml.reserved_uom_qty, precision_rounding=rounding) >= 0:
ml.write({
'qty_done': new_quantity_done,
'lot_id': self.lot_producing_id and self.lot_producing_id.id,
})
else:
new_qty_reserved = ml.product_uom_qty - new_quantity_done
new_qty_reserved = ml.reserved_uom_qty - new_quantity_done
default = {
'product_uom_qty': new_quantity_done,
'reserved_uom_qty': new_quantity_done,
'qty_done': new_quantity_done,
'lot_id': self.lot_producing_id and self.lot_producing_id.id,
}
ml.copy(default=default)
ml.with_context(bypass_reservation_update=True).write({
'product_uom_qty': new_qty_reserved,
'reserved_uom_qty': new_qty_reserved,
'qty_done': 0
})
@@ -120,7 +120,7 @@ class MrpProduction(models.Model):
'product_id': self.product_id.id,
'location_id': subcontract_move_id.location_id.id,
'location_dest_id': subcontract_move_id.location_dest_id.id,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'product_uom_id': self.product_uom_id.id,
'qty_done': quantity,
'lot_id': self.lot_producing_id and self.lot_producing_id.id,
@@ -128,10 +128,10 @@ class MrpProduction(models.Model):
if not self._get_quantity_to_backorder():
ml_reserved = subcontract_move_id.move_line_ids.filtered(lambda ml:
float_is_zero(ml.qty_done, precision_rounding=ml.product_uom_id.rounding) and
not float_is_zero(ml.product_uom_qty, precision_rounding=ml.product_uom_id.rounding))
not float_is_zero(ml.reserved_uom_qty, precision_rounding=ml.product_uom_id.rounding))
ml_reserved.unlink()
for ml in subcontract_move_id.move_line_ids:
ml.product_uom_qty = ml.qty_done
ml.reserved_uom_qty = ml.qty_done
subcontract_move_id._recompute_state()
def _subcontracting_filter_to_done(self):
@@ -22,10 +22,10 @@
<field name="lot_id"
attrs="{'invisible': [('tracking', 'not in', ('serial', 'lot'))], 'required': [('tracking', 'in', ('serial', 'lot'))]}"
context="{'default_product_id': product_id, 'default_company_id': company_id}"/>
<field name="product_uom_qty" readonly="1" force_save="1"/>
<field name="reserved_uom_qty" readonly="1" force_save="1"/>
<field name="qty_done"
decoration-warning="product_uom_qty &lt; qty_done"
decoration-success="product_uom_qty == qty_done"/>
decoration-warning="reserved_uom_qty &lt; qty_done"
decoration-success="reserved_uom_qty == qty_done"/>
<field name="product_uom_id" groups="uom.group_uom"/>
</tree>
</field>
+1 -1
View File
@@ -821,7 +821,7 @@ class PosOrder(models.Model):
'lines': [[0, 0, line] for line in order.lines.export_for_ui()],
'statement_ids': [[0, 0, payment] for payment in order.payment_ids.export_for_ui()],
'name': order.pos_reference,
'uid': re.search('([0-9-] r){14}', order.pos_reference).group(0),
'uid': re.search('([0-9-]){14}', order.pos_reference).group(0),
'amount_paid': order.amount_paid,
'amount_total': order.amount_total,
'amount_tax': order.amount_tax,
+2 -2
View File
@@ -141,7 +141,7 @@ class StockPicking(models.Model):
else:
move._action_assign()
for move_line in move.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
if float_compare(move.product_uom_qty, move.quantity_done, precision_rounding=move.product_uom.rounding) > 0:
remaining_qty = move.product_uom_qty - move.quantity_done
ml_vals = move._prepare_move_line_vals()
@@ -151,7 +151,7 @@ class StockPicking(models.Model):
else:
move._action_assign()
for move_line in move.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
if float_compare(move.product_uom_qty, move.quantity_done, precision_rounding=move.product_uom.rounding) > 0:
remaining_qty = move.product_uom_qty - move.quantity_done
ml_vals = move._prepare_move_line_vals()
@@ -58,7 +58,7 @@ class TestCreatePicking(common.TestProductCommon):
# Validate first shipment
self.picking = self.po.picking_ids[0]
for ml in self.picking.move_line_ids:
ml.qty_done = ml.product_uom_qty
ml.qty_done = ml.reserved_uom_qty
self.picking._action_done()
self.assertEqual(self.po.order_line.mapped('qty_received'), [7.0], 'Purchase: all products should be received')
+1 -1
View File
@@ -579,7 +579,7 @@ class Repair(models.Model):
'location_dest_id': repair.location_id.id,
'move_line_ids': [(0, 0, {'product_id': repair.product_id.id,
'lot_id': repair.lot_id.id,
'product_uom_qty': 0, # bypass reservation here
'reserved_uom_qty': 0, # bypass reservation here
'product_uom_id': repair.product_uom.id or repair.product_id.uom_id.id,
'qty_done': repair.product_qty,
'package_id': False,
@@ -83,7 +83,7 @@ class TestSaleExpectedDate(ValuationReconciliationTestCommon):
# Check effective date, it should be date on which the first shipment successfully delivered to customer
picking = sale_order.picking_ids[0]
for ml in picking.move_line_ids:
ml.qty_done = ml.product_uom_qty
ml.qty_done = ml.reserved_uom_qty
picking._action_done()
self.assertEqual(picking.state, 'done', "Picking not processed correctly!")
self.assertEqual(fields.Date.today(), sale_order.effective_date.date(), "Wrong effective date on sale order!")
+3 -3
View File
@@ -556,7 +556,7 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
'move_line_ids': [
(0, 0, {
'product_id': item1.id,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'qty_done': 1,
'product_uom_id': uom_dozen.id,
'location_id': so1.picking_ids.location_id.id,
@@ -564,7 +564,7 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
}),
(0, 0, {
'product_id': item1.id,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'qty_done': 1,
'product_uom_id': uom_dozen.id,
'location_id': so1.picking_ids.location_id.id,
@@ -572,7 +572,7 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
}),
(0, 0, {
'product_id': item1.id,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'qty_done': 1,
'product_uom_id': uom_dozen.id,
'location_id': so1.picking_ids.location_id.id,
+6 -6
View File
@@ -87,7 +87,7 @@ class Location(models.Model):
_sql_constraints = [('barcode_company_uniq', 'unique (barcode,company_id)', 'The barcode for a location must be unique per company !'),
('inventory_freq_nonneg', 'check(cyclic_inventory_frequency >= 0)', 'The inventory frequency (days) for a location must be non-negative')]
@api.depends('outgoing_move_line_ids.product_qty', 'incoming_move_line_ids.product_qty',
@api.depends('outgoing_move_line_ids.reserved_qty', 'incoming_move_line_ids.reserved_qty',
'outgoing_move_line_ids.state', 'incoming_move_line_ids.state',
'outgoing_move_line_ids.product_id.weight', 'outgoing_move_line_ids.product_id.weight',
'quant_ids.quantity', 'quant_ids.product_id.weight')
@@ -101,9 +101,9 @@ class Location(models.Model):
location.net_weight += quant.product_id.weight * quant.quantity
location.forecast_weight = location.net_weight
for line in incoming_move_lines:
location.forecast_weight += line.product_id.weight * line.product_qty
location.forecast_weight += line.product_id.weight * line.reserved_qty
for line in outgoing_move_lines:
location.forecast_weight -= line.product_id.weight * line.product_qty
location.forecast_weight -= line.product_id.weight * line.reserved_qty
@api.depends('name', 'location_id.complete_name', 'usage')
def _compute_complete_name(self):
@@ -168,7 +168,7 @@ class Location(models.Model):
for f in {'usage', 'scrap_location'}))
reserved_quantities = self.env['stock.move.line'].search_count([
('location_id', 'in', modified_locations.ids),
('product_qty', '>', 0),
('reserved_qty', '>', 0),
])
if reserved_quantities:
raise UserError(_(
@@ -264,7 +264,7 @@ class Location(models.Model):
('product_id', '=', product.id),
('location_dest_id', 'in', locations.ids),
('state', 'not in', ['draft', 'done', 'cancel'])
], ['location_dest_id', 'product_id', 'product_qty:array_agg', 'qty_done:array_agg', 'product_uom_id:array_agg'], ['location_dest_id'])
], ['location_dest_id', 'product_id', 'reserved_qty:array_agg', 'qty_done:array_agg', 'product_uom_id:array_agg'], ['location_dest_id'])
quant_data = self.env['stock.quant'].read_group([
('product_id', '=', product.id),
('location_id', 'in', locations.ids),
@@ -273,7 +273,7 @@ class Location(models.Model):
for values in move_line_data:
uoms = self.env['uom.uom'].browse(values['product_uom_id'])
qty_done = sum(max(ml_uom._compute_quantity(float(qty), product.uom_id), float(qty_reserved))
for qty_reserved, qty, ml_uom in zip(values['product_qty'], values['qty_done'], list(uoms)))
for qty_reserved, qty, ml_uom in zip(values['reserved_qty'], values['qty_done'], list(uoms)))
qty_by_location[values['location_dest_id'][0]] = qty_done
for values in quant_data:
qty_by_location[values['location_id'][0]] += values['quantity']
+19 -19
View File
@@ -130,7 +130,7 @@ class StockMove(models.Model):
picking_type_id = fields.Many2one('stock.picking.type', 'Operation Type', compute='_compute_picking_type_id', store=True, check_company=True)
is_inventory = fields.Boolean('Inventory')
move_line_ids = fields.One2many('stock.move.line', 'move_id')
move_line_nosuggest_ids = fields.One2many('stock.move.line', 'move_id', domain=['|', ('product_qty', '=', 0.0), ('qty_done', '!=', 0.0)])
move_line_nosuggest_ids = fields.One2many('stock.move.line', 'move_id', domain=['|', ('reserved_qty', '=', 0.0), ('qty_done', '!=', 0.0)])
origin_returned_move_id = fields.Many2one(
'stock.move', 'Origin return move', copy=False, index=True,
help='Move that created the return move', check_company=True)
@@ -376,7 +376,7 @@ class StockMove(models.Model):
detect errors. """
raise UserError(_('The requested operation cannot be processed because of a programming error setting the `product_qty` field instead of the `product_uom_qty`.'))
@api.depends('move_line_ids.product_qty')
@api.depends('move_line_ids.reserved_qty')
def _compute_reserved_availability(self):
""" Fill the `availability` field on a stock move, which is the actual reserved quantity
and is represented by the aggregated `product_qty` on the linked move lines. If the move
@@ -385,13 +385,13 @@ class StockMove(models.Model):
if not any(self._ids):
# onchange
for move in self:
reserved_availability = sum(move.move_line_ids.mapped('product_qty'))
reserved_availability = sum(move.move_line_ids.mapped('reserved_qty'))
move.reserved_availability = move.product_id.uom_id._compute_quantity(
reserved_availability, move.product_uom, rounding_method='HALF-UP')
else:
# compute
result = {data['move_id'][0]: data['product_qty'] for data in
self.env['stock.move.line'].read_group([('move_id', 'in', self.ids)], ['move_id', 'product_qty'], ['move_id'])}
result = {data['move_id'][0]: data['reserved_qty'] for data in
self.env['stock.move.line'].read_group([('move_id', 'in', self.ids)], ['move_id', 'reserved_qty'], ['move_id'])}
for move in self:
move.reserved_availability = move.product_id.uom_id._compute_quantity(
result.get(move.id, 0.0), move.product_uom, rounding_method='HALF-UP')
@@ -489,7 +489,7 @@ class StockMove(models.Model):
@api.depends('move_line_ids', 'move_line_ids.lot_id', 'move_line_ids.qty_done')
def _compute_lot_ids(self):
domain_nosuggest = [('move_id', 'in', self.ids), ('lot_id', '!=', False), '|', ('qty_done', '!=', 0.0), ('product_qty', '=', 0.0)]
domain_nosuggest = [('move_id', 'in', self.ids), ('lot_id', '!=', False), '|', ('qty_done', '!=', 0.0), ('reserved_qty', '=', 0.0)]
domain_suggest = [('move_id', 'in', self.ids), ('lot_id', '!=', False), ('qty_done', '!=', 0.0)]
lots_by_move_id_list = []
for domain in [domain_nosuggest, domain_suggest]:
@@ -754,7 +754,7 @@ class StockMove(models.Model):
ml_to_update, ml_to_unlink = self.env['stock.move.line'].browse(ml_to_update), self.env['stock.move.line'].browse(ml_to_unlink)
moves_not_to_recompute = self.env['stock.move'].browse(moves_not_to_recompute)
ml_to_update.write({'product_uom_qty': 0})
ml_to_update.write({'reserved_uom_qty': 0})
ml_to_unlink.unlink()
# `write` on `stock.move.line` doesn't call `_recompute_state` (unlike to `unlink`),
# so it must be called for each move where no move line has been deleted.
@@ -1293,9 +1293,9 @@ class StockMove(models.Model):
uom_quantity = float_round(uom_quantity, precision_digits=rounding)
uom_quantity_back_to_product_uom = self.product_uom._compute_quantity(uom_quantity, self.product_id.uom_id, rounding_method='HALF-UP')
if float_compare(quantity, uom_quantity_back_to_product_uom, precision_digits=rounding) == 0:
vals = dict(vals, product_uom_qty=uom_quantity)
vals = dict(vals, reserved_uom_qty=uom_quantity)
else:
vals = dict(vals, product_uom_qty=quantity, product_uom_id=self.product_id.uom_id.id)
vals = dict(vals, reserved_uom_qty=quantity, product_uom_id=self.product_id.uom_id.id)
package = None
if reserved_quant:
package = reserved_quant.package_id
@@ -1366,7 +1366,7 @@ class StockMove(models.Model):
uom_quantity = float_round(uom_quantity, precision_digits=rounding)
uom_quantity_back_to_product_uom = to_update.product_uom_id._compute_quantity(uom_quantity, self.product_id.uom_id, rounding_method='HALF-UP')
if to_update and float_compare(quantity, uom_quantity_back_to_product_uom, precision_digits=rounding) == 0:
to_update.with_context(bypass_reservation_update=True).product_uom_qty += uom_quantity
to_update.with_context(bypass_reservation_update=True).reserved_uom_qty += uom_quantity
else:
if self.product_id.tracking == 'serial':
self.env['stock.move.line'].create([self._prepare_move_line_vals(quantity=1, reserved_quant=reserved_quant) for i in range(int(quantity))])
@@ -1388,7 +1388,7 @@ class StockMove(models.Model):
def _action_assign(self):
""" Reserve stock moves by creating their stock move lines. A stock move is
considered reserved once the sum of `product_qty` for all its move lines is
considered reserved once the sum of `reserved_qty` for all its move lines is
equal to its `product_qty`. If it is less, the stock move is considered
partially available.
"""
@@ -1425,7 +1425,7 @@ class StockMove(models.Model):
qty_done += ml.product_uom_id._compute_quantity(ml.qty_done, ml.product_id.uom_id)
grouped_move_lines_out[k] = qty_done
for k, g in groupby(move_lines_out_reserved, key=_keys_out_groupby):
grouped_move_lines_out[k] = sum(self.env['stock.move.line'].concat(*g).mapped('product_qty'))
grouped_move_lines_out[k] = sum(self.env['stock.move.line'].concat(*g).mapped('reserved_qty'))
available_move_lines = {key: grouped_move_lines_in[key] - grouped_move_lines_out.get(key, 0) for key in grouped_move_lines_in}
# pop key if the quantity available amount to 0
return dict((k, v) for k, v in available_move_lines.items() if v)
@@ -1472,7 +1472,7 @@ class StockMove(models.Model):
not ml.package_id and
not ml.owner_id)
if to_update:
to_update[0].product_uom_qty += move.product_id.uom_id._compute_quantity(
to_update[0].reserved_uom_qty += move.product_id.uom_id._compute_quantity(
missing_reserved_quantity, move.product_uom, rounding_method='HALF-UP')
else:
move_line_vals_list.append(move._prepare_move_line_vals(quantity=missing_reserved_quantity))
@@ -1509,11 +1509,11 @@ class StockMove(models.Model):
available_move_lines = _get_available_move_lines(move)
if not available_move_lines:
continue
for move_line in move.move_line_ids.filtered(lambda m: m.product_qty):
for move_line in move.move_line_ids.filtered(lambda m: m.reserved_qty):
if available_move_lines.get((move_line.location_id, move_line.lot_id, move_line.result_package_id, move_line.owner_id)):
available_move_lines[(move_line.location_id, move_line.lot_id, move_line.result_package_id, move_line.owner_id)] -= move_line.product_qty
available_move_lines[(move_line.location_id, move_line.lot_id, move_line.result_package_id, move_line.owner_id)] -= move_line.reserved_qty
for (location_id, lot_id, package_id, owner_id), quantity in available_move_lines.items():
need = move.product_qty - sum(move.move_line_ids.mapped('product_qty'))
need = move.product_qty - sum(move.move_line_ids.mapped('reserved_qty'))
# `quantity` is what is brought by chained done move lines. We double check
# here this quantity is available on the quants themselves. If not, this
# could be the result of an inventory adjustment that removed totally of
@@ -1788,7 +1788,7 @@ class StockMove(models.Model):
def _set_quantity_done_prepare_vals(self, qty):
res = []
for ml in self.move_line_ids:
ml_qty = ml.product_uom_qty - ml.qty_done
ml_qty = ml.reserved_uom_qty - ml.qty_done
if float_compare(ml_qty, 0, precision_rounding=ml.product_uom_id.rounding) <= 0:
continue
# Convert move line qty into move uom
@@ -1812,7 +1812,7 @@ class StockMove(models.Model):
break
for ml in self.move_line_ids:
if float_is_zero(ml.product_uom_qty, precision_rounding=ml.product_uom_id.rounding) and float_is_zero(ml.qty_done, precision_rounding=ml.product_uom_id.rounding):
if float_is_zero(ml.reserved_uom_qty, precision_rounding=ml.product_uom_id.rounding) and float_is_zero(ml.qty_done, precision_rounding=ml.product_uom_id.rounding):
res.append((2, ml.id))
if float_compare(qty, 0.0, precision_rounding=self.product_uom.rounding) > 0:
@@ -1845,7 +1845,7 @@ class StockMove(models.Model):
for move_line in move.move_line_ids:
if move.has_tracking != 'none' and not (move_line.lot_id or move_line.lot_name):
continue
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
def _clear_quantities_to_zero(self):
self.filtered(lambda m: m.state in ('partially_available', 'assigned')).move_line_ids.qty_done = 0
+46 -46
View File
@@ -29,10 +29,10 @@ class StockMoveLine(models.Model):
product_id = fields.Many2one('product.product', 'Product', ondelete="cascade", check_company=True, domain="[('type', '!=', 'service'), '|', ('company_id', '=', False), ('company_id', '=', company_id)]")
product_uom_id = fields.Many2one('uom.uom', 'Unit of Measure', required=True, domain="[('category_id', '=', product_uom_category_id)]")
product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id')
product_qty = fields.Float(
reserved_qty = fields.Float(
'Real Reserved Quantity', digits=0, copy=False,
compute='_compute_product_qty', inverse='_set_product_qty', store=True)
product_uom_qty = fields.Float(
compute='_compute_reserved_qty', inverse='_set_product_qty', store=True)
reserved_uom_qty = fields.Float(
'Reserved', default=0.0, digits='Product Unit of Measure', required=True, copy=False)
qty_done = fields.Float('Done', default=0.0, digits='Product Unit of Measure', copy=False)
package_id = fields.Many2one(
@@ -94,17 +94,17 @@ class StockMoveLine(models.Model):
def _search_picking_type_id(self, operator, value):
return [('picking_id.picking_type_id', operator, value)]
@api.depends('product_id', 'product_uom_id', 'product_uom_qty')
def _compute_product_qty(self):
@api.depends('product_id', 'product_uom_id', 'reserved_uom_qty')
def _compute_reserved_qty(self):
for line in self:
line.product_qty = line.product_uom_id._compute_quantity(line.product_uom_qty, line.product_id.uom_id, rounding_method='HALF-UP')
line.reserved_qty = line.product_uom_id._compute_quantity(line.reserved_uom_qty, line.product_id.uom_id, rounding_method='HALF-UP')
def _set_product_qty(self):
""" The meaning of product_qty field changed lately and is now a functional field computing the quantity
def _set_reserved_qty(self):
""" The meaning of reserved_qty field changed lately and is now a functional field computing the quantity
in the default product UoM. This code has been added to raise an error if a write is made given a value
for `product_qty`, where the same write should set the `product_uom_qty` field instead, in order to
for `reserved_qty`, where the same write should set the `reserved_uom_qty` field instead, in order to
detect errors. """
raise UserError(_('The requested operation cannot be processed because of a programming error setting the `product_qty` field instead of the `product_uom_qty`.'))
raise UserError(_('The requested operation cannot be processed because of a programming error setting the `reserved_qty` field instead of the `reserved_uom_qty`.'))
@api.constrains('lot_id', 'product_id')
def _check_lot_product(self):
@@ -116,10 +116,10 @@ class StockMoveLine(models.Model):
product_name=line.product_id.display_name
))
@api.constrains('product_uom_qty')
@api.constrains('reserved_uom_qty')
def _check_reserved_done_quantity(self):
for move_line in self:
if move_line.state == 'done' and not float_is_zero(move_line.product_uom_qty, precision_digits=self.env['decimal.precision'].precision_get('Product Unit of Measure')):
if move_line.state == 'done' and not float_is_zero(move_line.reserved_uom_qty, precision_digits=self.env['decimal.precision'].precision_get('Product Unit of Measure')):
raise ValidationError(_('A done move line should never have a reserved quantity.'))
@api.constrains('qty_done')
@@ -215,7 +215,7 @@ class StockMoveLine(models.Model):
def _get_putaway_additional_qty(self):
addtional_qty = {}
for ml in self._origin:
qty = max(ml.product_uom_id._compute_quantity(ml.qty_done, ml.product_id.uom_id), ml.product_uom_qty)
qty = max(ml.product_uom_id._compute_quantity(ml.qty_done, ml.product_id.uom_id), ml.reserved_uom_qty)
addtional_qty[ml.location_dest_id.id] = addtional_qty.get(ml.location_dest_id.id, 0) - qty
return addtional_qty
@@ -226,7 +226,7 @@ class StockMoveLine(models.Model):
ON
stock_move_line (id, company_id, product_id, lot_id, location_id, owner_id, package_id)
WHERE
(state IS NULL OR state NOT IN ('cancel', 'done')) AND product_qty > 0""")
(state IS NULL OR state NOT IN ('cancel', 'done')) AND reserved_qty > 0""")
@api.model_create_multi
def create(self, vals_list):
@@ -334,31 +334,31 @@ class StockMoveLine(models.Model):
package_level.unlink()
# When we try to write on a reserved move line any fields from `triggers` or directly
# `product_uom_qty` (the actual reserved quantity), we need to make sure the associated
# `reserved_uom_qty` (the actual reserved quantity), we need to make sure the associated
# quants are correctly updated in order to not make them out of sync (i.e. the sum of the
# move lines `product_uom_qty` should always be equal to the sum of `reserved_quantity` on
# move lines `reserved_uom_qty` should always be equal to the sum of `reserved_quantity` on
# the quants). If the new charateristics are not available on the quants, we chose to
# reserve the maximum possible.
if updates or 'product_uom_qty' in vals:
if updates or 'reserved_uom_qty' in vals:
for ml in self.filtered(lambda ml: ml.state in ['partially_available', 'assigned'] and ml.product_id.type == 'product'):
if 'product_uom_qty' in vals:
new_product_uom_qty = ml.product_uom_id._compute_quantity(
vals['product_uom_qty'], ml.product_id.uom_id, rounding_method='HALF-UP')
# Make sure `product_uom_qty` is not negative.
if float_compare(new_product_uom_qty, 0, precision_rounding=ml.product_id.uom_id.rounding) < 0:
if 'reserved_uom_qty' in vals:
new_reserved_uom_qty = ml.product_uom_id._compute_quantity(
vals['reserved_uom_qty'], ml.product_id.uom_id, rounding_method='HALF-UP')
# Make sure `reserved_uom_qty` is not negative.
if float_compare(new_reserved_uom_qty, 0, precision_rounding=ml.product_id.uom_id.rounding) < 0:
raise UserError(_('Reserving a negative quantity is not allowed.'))
else:
new_product_uom_qty = ml.product_qty
new_reserved_uom_qty = ml.reserved_qty
# Unreserve the old charateristics of the move line.
if not ml.move_id._should_bypass_reservation(ml.location_id):
try:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.reserved_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
except UserError:
# If we were not able to unreserve on tracked quants, we can use untracked ones.
if ml.lot_id:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.reserved_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
else:
raise
@@ -366,22 +366,22 @@ class StockMoveLine(models.Model):
if not ml.move_id._should_bypass_reservation(updates.get('location_id', ml.location_id)):
reserved_qty = 0
try:
q = Quant._update_reserved_quantity(ml.product_id, updates.get('location_id', ml.location_id), new_product_uom_qty, lot_id=updates.get('lot_id', ml.lot_id),
q = Quant._update_reserved_quantity(ml.product_id, updates.get('location_id', ml.location_id), new_reserved_uom_qty, lot_id=updates.get('lot_id', ml.lot_id),
package_id=updates.get('package_id', ml.package_id), owner_id=updates.get('owner_id', ml.owner_id), strict=True)
reserved_qty = sum([x[1] for x in q])
except UserError:
if updates.get('lot_id'):
# If we were not able to reserve on tracked quants, we can use untracked ones.
try:
q = Quant._update_reserved_quantity(ml.product_id, updates.get('location_id', ml.location_id), new_product_uom_qty, lot_id=False,
q = Quant._update_reserved_quantity(ml.product_id, updates.get('location_id', ml.location_id), new_reserved_uom_qty, lot_id=False,
package_id=updates.get('package_id', ml.package_id), owner_id=updates.get('owner_id', ml.owner_id), strict=True)
reserved_qty = sum([x[1] for x in q])
except UserError:
pass
if reserved_qty != new_product_uom_qty:
new_product_uom_qty = ml.product_id.uom_id._compute_quantity(reserved_qty, ml.product_uom_id, rounding_method='HALF-UP')
if reserved_qty != new_reserved_uom_qty:
new_reserved_uom_qty = ml.product_id.uom_id._compute_quantity(reserved_qty, ml.product_uom_id, rounding_method='HALF-UP')
moves_to_recompute_state |= ml.move_id
ml.with_context(bypass_reservation_update=True).product_uom_qty = new_product_uom_qty
ml.with_context(bypass_reservation_update=True).reserved_uom_qty = new_reserved_uom_qty
# When editing a done move line, the reserved availability of a potential chained move is impacted. Take care of running again `_action_assign` on the concerned moves.
if updates or 'qty_done' in vals:
@@ -443,7 +443,7 @@ class StockMoveLine(models.Model):
# this is what move's `action_done` will do. So, we replicate the behavior here.
if updates or 'qty_done' in vals:
moves = self.filtered(lambda ml: ml.move_id.state == 'done').mapped('move_id')
moves |= self.filtered(lambda ml: ml.move_id.state not in ('done', 'cancel') and ml.move_id.picking_id.immediate_transfer and not ml.product_uom_qty).mapped('move_id')
moves |= self.filtered(lambda ml: ml.move_id.state not in ('done', 'cancel') and ml.move_id.picking_id.immediate_transfer and not ml.reserved_uom_qty).mapped('move_id')
for move in moves:
move.product_uom_qty = move.quantity_done
next_moves._do_unreserve()
@@ -464,12 +464,12 @@ class StockMoveLine(models.Model):
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
for ml in self:
# Unlinking a move line should unreserve.
if ml.product_id.type == 'product' and not ml.move_id._should_bypass_reservation(ml.location_id) and not float_is_zero(ml.product_qty, precision_digits=precision):
if ml.product_id.type == 'product' and not ml.move_id._should_bypass_reservation(ml.location_id) and not float_is_zero(ml.reserved_qty, precision_digits=precision):
try:
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.reserved_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
except UserError:
if ml.lot_id:
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.reserved_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
elif not self.env.context.get(MODULE_UNINSTALL_FLAG, False):
raise # pylint: disable=raise-unlink-override
moves = self.mapped('move_id')
@@ -566,16 +566,16 @@ class StockMoveLine(models.Model):
rounding = ml.product_uom_id.rounding
# if this move line is force assigned, unreserve elsewhere if needed
if not ml.move_id._should_bypass_reservation(ml.location_id) and float_compare(ml.qty_done, ml.product_uom_qty, precision_rounding=rounding) > 0:
if not ml.move_id._should_bypass_reservation(ml.location_id) and float_compare(ml.qty_done, ml.reserved_uom_qty, precision_rounding=rounding) > 0:
qty_done_product_uom = ml.product_uom_id._compute_quantity(ml.qty_done, ml.product_id.uom_id, rounding_method='HALF-UP')
extra_qty = qty_done_product_uom - ml.product_qty
extra_qty = qty_done_product_uom - ml.reserved_qty
ml._free_reservation(ml.product_id, ml.location_id, extra_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, ml_ids_to_ignore=ml_ids_to_ignore)
# unreserve what's been reserved
if not ml.move_id._should_bypass_reservation(ml.location_id) and ml.product_id.type == 'product' and ml.product_qty:
if not ml.move_id._should_bypass_reservation(ml.location_id) and ml.product_id.type == 'product' and ml.reserved_qty:
try:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.reserved_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
except UserError:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.reserved_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
# move what's been actually done
quantity = ml.product_uom_id._compute_quantity(ml.qty_done, ml.move_id.product_id.uom_id, rounding_method='HALF-UP')
@@ -591,7 +591,7 @@ class StockMoveLine(models.Model):
ml_ids_to_ignore.add(ml.id)
# Reset the reserved quantity as we just moved it to the destination location.
mls_todo.with_context(bypass_reservation_update=True).write({
'product_uom_qty': 0.00,
'reserved_uom_qty': 0.00,
'date': fields.Datetime.now(),
})
@@ -686,7 +686,7 @@ class StockMoveLine(models.Model):
('location_id', '=', location_id.id),
('owner_id', '=', owner_id.id if owner_id else False),
('package_id', '=', package_id.id if package_id else False),
('product_qty', '>', 0.0),
('reserved_qty', '>', 0.0),
('id', 'not in', tuple(ml_ids_to_ignore)),
]
@@ -706,11 +706,11 @@ class StockMoveLine(models.Model):
rounding = self.product_uom_id.rounding
for candidate in outdated_candidates:
if float_compare(candidate.product_qty, quantity, precision_rounding=rounding) <= 0:
quantity -= candidate.product_qty
if float_compare(candidate.reserved_qty, quantity, precision_rounding=rounding) <= 0:
quantity -= candidate.reserved_qty
if candidate.qty_done:
move_to_recompute_state |= candidate.move_id
candidate.product_uom_qty = 0.0
candidate.reserved_uom_qty = 0.0
else:
to_unlink_candidate_ids.add(candidate.id)
if float_is_zero(quantity, precision_rounding=rounding):
@@ -718,10 +718,10 @@ class StockMoveLine(models.Model):
else:
# split this move line and assign the new part to our extra move
quantity_split = float_round(
candidate.product_qty - quantity,
candidate.reserved_qty - quantity,
precision_rounding=self.product_uom_id.rounding,
rounding_method='UP')
candidate.product_uom_qty = self.product_id.uom_id._compute_quantity(quantity_split, candidate.product_uom_id, rounding_method='HALF-UP')
candidate.reserved_uom_qty = self.product_id.uom_id._compute_quantity(quantity_split, candidate.product_uom_id, rounding_method='HALF-UP')
move_to_recompute_state |= candidate.move_id
break
self.env['stock.move.line'].browse(to_unlink_candidate_ids).unlink()
+3 -3
View File
@@ -74,8 +74,8 @@ class StockPackageLevel(models.Model):
for rec, quant in ml_update_dict.items():
rec.qty_done = quant
else:
package_level.move_line_ids.filtered(lambda ml: ml.product_qty == 0).unlink()
package_level.move_line_ids.filtered(lambda ml: ml.product_qty != 0).write({'qty_done': 0})
package_level.move_line_ids.filtered(lambda ml: ml.reserved_qty == 0).unlink()
package_level.move_line_ids.filtered(lambda ml: ml.reserved_qty != 0).write({'qty_done': 0})
@api.depends('move_line_ids', 'move_line_ids.package_id', 'move_line_ids.result_package_id')
def _compute_fresh_pack(self):
@@ -95,7 +95,7 @@ class StockPackageLevel(models.Model):
elif package_level.move_line_ids and not package_level.move_line_ids.filtered(lambda ml: ml.state == 'done'):
if package_level.is_fresh_package:
package_level.state = 'new'
elif package_level._check_move_lines_map_quant_package(package_level.package_id, 'product_uom_qty'):
elif package_level._check_move_lines_map_quant_package(package_level.package_id, 'reserved_uom_qty'):
package_level.state = 'assigned'
else:
package_level.state = 'confirmed'
+11 -11
View File
@@ -356,7 +356,7 @@ class Picking(models.Model):
default=lambda self: self.env.user)
move_line_ids = fields.One2many('stock.move.line', 'picking_id', 'Operations')
move_line_ids_without_package = fields.One2many('stock.move.line', 'picking_id', 'Operations without package', domain=['|',('package_level_id', '=', False), ('picking_type_entire_packs', '=', False)])
move_line_nosuggest_ids = fields.One2many('stock.move.line', 'picking_id', domain=[('product_qty', '=', 0.0)])
move_line_nosuggest_ids = fields.One2many('stock.move.line', 'picking_id', domain=[('reserved_qty', '=', 0.0)])
move_line_exist = fields.Boolean(
'Has Pack Operations', compute='_compute_move_line_exist',
help='Check the existence of pack operation on the picking')
@@ -883,7 +883,7 @@ class Picking(models.Model):
return move_ids_without_package.filtered(lambda move: not move.scrap_ids)
def _check_move_lines_map_quant_package(self, package):
return package._check_move_lines_map_quant(self.move_line_ids.filtered(lambda ml: ml.package_id == package), 'product_qty')
return package._check_move_lines_map_quant(self.move_line_ids.filtered(lambda ml: ml.package_id == package), 'reserved_qty')
def _get_entire_pack_location_dest(self, move_line_ids):
location_dest_ids = move_line_ids.mapped('location_dest_id')
@@ -952,7 +952,7 @@ class Picking(models.Model):
picking_type = picking.picking_type_id
precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure')
no_quantities_done = all(float_is_zero(move_line.qty_done, precision_digits=precision_digits) for move_line in picking.move_line_ids.filtered(lambda m: m.state not in ('done', 'cancel')))
no_reserved_quantities = all(float_is_zero(move_line.product_qty, precision_rounding=move_line.product_uom_id.rounding) for move_line in picking.move_line_ids)
no_reserved_quantities = all(float_is_zero(move_line.reserved_qty, precision_rounding=move_line.product_uom_id.rounding) for move_line in picking.move_line_ids)
if no_reserved_quantities and no_quantities_done:
pickings_without_quantities |= picking
@@ -1356,28 +1356,28 @@ class Picking(models.Model):
precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure')
if float_is_zero(move_line_ids[0].qty_done, precision_digits=precision_digits):
for line in move_line_ids:
line.qty_done = line.product_uom_qty
line.qty_done = line.reserved_uom_qty
for ml in move_line_ids:
if float_compare(ml.qty_done, ml.product_uom_qty,
if float_compare(ml.qty_done, ml.reserved_uom_qty,
precision_rounding=ml.product_uom_id.rounding) >= 0:
move_lines_to_pack |= ml
else:
quantity_left_todo = float_round(
ml.product_uom_qty - ml.qty_done,
ml.reserved_uom_qty - ml.qty_done,
precision_rounding=ml.product_uom_id.rounding,
rounding_method='UP')
done_to_keep = ml.qty_done
new_move_line = ml.copy(
default={'product_uom_qty': 0, 'qty_done': ml.qty_done})
vals = {'product_uom_qty': quantity_left_todo, 'qty_done': 0.0}
default={'reserved_uom_qty': 0, 'qty_done': ml.qty_done})
vals = {'reserved_uom_qty': quantity_left_todo, 'qty_done': 0.0}
if pick.picking_type_id.code == 'incoming':
if ml.lot_id:
vals['lot_id'] = False
if ml.lot_name:
vals['lot_name'] = False
ml.write(vals)
new_move_line.write({'product_uom_qty': done_to_keep})
new_move_line.write({'reserved_uom_qty': done_to_keep})
move_lines_to_pack |= new_move_line
if not package.package_type_id:
package_type = move_lines_to_pack.move_id.product_packaging_id.package_type_id
@@ -1387,7 +1387,7 @@ class Picking(models.Model):
default_dest_location = move_lines_to_pack._get_default_dest_location()
move_lines_to_pack.location_dest_id = default_dest_location._get_putaway_strategy(
product=move_lines_to_pack.product_id,
quantity=move_lines_to_pack.product_uom_qty,
quantity=move_lines_to_pack.reserved_uom_qty,
package=package)
move_lines_to_pack.write({
'result_package_id': package.id,
@@ -1419,7 +1419,7 @@ class Picking(models.Model):
and not ml.result_package_id
)
if not move_line_ids:
move_line_ids = picking_move_lines.filtered(lambda ml: float_compare(ml.product_uom_qty, 0.0,
move_line_ids = picking_move_lines.filtered(lambda ml: float_compare(ml.reserved_uom_qty, 0.0,
precision_rounding=ml.product_uom_id.rounding) > 0 and float_compare(ml.qty_done, 0.0,
precision_rounding=ml.product_uom_id.rounding) == 0)
if move_line_ids:
+1 -1
View File
@@ -1011,7 +1011,7 @@ class QuantPackage(models.Model):
move_line_to_modify = self.env['stock.move.line'].search([
('package_id', '=', package.id),
('state', 'in', ('assigned', 'partially_available')),
('product_qty', '!=', 0),
('reserved_qty', '!=', 0),
])
move_line_to_modify.write({'package_id': False})
package.mapped('quant_ids').sudo().write({'package_id': False})
+1 -1
View File
@@ -495,7 +495,7 @@ class StockMove(models.Model):
for move in picking.move_ids:
# For assigned moves
for move_line in move._get_move_lines():
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
# Create move line for remaining qty
missing_to_do = move.product_qty - move.quantity_done
missing_to_do = move.product_uom._compute_quantity(missing_to_do, move.product_uom, rounding_method='HALF-UP')
+10 -10
View File
@@ -219,13 +219,13 @@ class ReceptionReport(models.AbstractModel):
out.move_line_ids.move_id = new_out
assigned_amount = 0
for move_line_id in new_out.move_line_ids:
if assigned_amount + move_line_id.product_qty > qty_to_link:
new_move_line = move_line_id.copy({'product_uom_qty': 0, 'qty_done': 0})
new_move_line.product_uom_qty = move_line_id.product_uom_qty
move_line_id.product_uom_qty = out.product_id.uom_id._compute_quantity(qty_to_link - assigned_amount, out.product_uom, rounding_method='HALF-UP')
new_move_line.product_uom_qty -= out.product_id.uom_id._compute_quantity(move_line_id.product_qty, out.product_uom, rounding_method='HALF-UP')
if assigned_amount + move_line_id.reserved_qty > qty_to_link:
new_move_line = move_line_id.copy({'reserved_uom_qty': 0, 'qty_done': 0})
new_move_line.reserved_uom_qty = move_line_id.reserved_uom_qty
move_line_id.reserved_uom_qty = out.product_id.uom_id._compute_quantity(qty_to_link - assigned_amount, out.product_uom, rounding_method='HALF-UP')
new_move_line.reserved_uom_qty -= out.product_id.uom_id._compute_quantity(move_line_id.reserved_qty, out.product_uom, rounding_method='HALF-UP')
move_line_id.move_id = out
assigned_amount += move_line_id.product_qty
assigned_amount += move_line_id.reserved_qty
if float_compare(assigned_amount, qty_to_link, precision_rounding=out.product_id.uom_id.rounding) == 0:
break
@@ -282,10 +282,10 @@ class ReceptionReport(models.AbstractModel):
for move_line_id in new_out.move_line_ids:
if reserved_amount_to_remain <= 0:
break
if move_line_id.product_qty > reserved_amount_to_remain:
new_move_line = move_line_id.copy({'product_uom_qty': 0, 'qty_done': 0})
new_move_line.product_uom_qty = out.product_id.uom_id._compute_quantity(move_line_id.product_qty - reserved_amount_to_remain, move_line_id.product_uom_id, rounding_method='HALF-UP')
move_line_id.product_uom_qty -= new_move_line.product_uom_qty
if move_line_id.reserved_qty > reserved_amount_to_remain:
new_move_line = move_line_id.copy({'reserved_uom_qty': 0, 'qty_done': 0})
new_move_line.reserved_uom_qty = out.product_id.uom_id._compute_quantity(move_line_id.reserved_qty - reserved_amount_to_remain, move_line_id.product_uom_id, rounding_method='HALF-UP')
move_line_id.reserved_uom_qty -= new_move_line.reserved_uom_qty
new_move_line.move_id = out
break
else:
@@ -92,7 +92,7 @@
<span t-field="ml.product_id.description_picking"/>
</td>
<td>
<span t-if="o.state != 'done'" t-field="ml.product_uom_qty"/>
<span t-if="o.state != 'done'" t-field="ml.reserved_uom_qty"/>
<span t-if="o.state == 'done'" t-field="ml.qty_done"/>
<span t-field="ml.product_uom_id" groups="uom.group_uom"/>
</td>
@@ -40,7 +40,7 @@ class StockGenerate(TransactionCase):
move_lines_val.append({
'product_id': self.product_serial.id,
'product_uom_id': self.uom_unit.id,
'product_uom_qty': 1,
'reserved_uom_qty': 1,
'location_id': self.location.id,
'location_dest_id': self.location_dest.id
})
+38 -38
View File
@@ -74,7 +74,7 @@ class StockMove(TransactionCase):
# fill the move line
move_line = move1.move_line_ids[0]
self.assertEqual(move_line.product_qty, 100.0)
self.assertEqual(move_line.reserved_qty, 100.0)
self.assertEqual(move_line.qty_done, 0.0)
move_line.qty_done = 100.0
@@ -110,13 +110,13 @@ class StockMove(TransactionCase):
self.assertEqual(move1.state, 'assigned')
self.assertEqual(len(move1.move_line_ids), 1)
move_line = move1.move_line_ids[0]
self.assertEqual(move_line.product_qty, 5)
self.assertEqual(move_line.reserved_qty, 5)
move_line.lot_name = 'lot1'
move_line.qty_done = 5.0
self.assertEqual(move_line.product_qty, 5) # don't change reservation
self.assertEqual(move_line.reserved_qty, 5) # don't change reservation
move1._action_done()
self.assertEqual(move_line.product_qty, 0) # change reservation to 0 for done move
self.assertEqual(move_line.reserved_qty, 0) # change reservation to 0 for done move
self.assertEqual(move1.state, 'done')
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_lot, self.supplier_location), 0.0)
@@ -213,7 +213,7 @@ class StockMove(TransactionCase):
# fill the move line
move_line = move1.move_line_ids[0]
self.assertEqual(move_line.product_qty, 100.0)
self.assertEqual(move_line.reserved_qty, 100.0)
self.assertEqual(move_line.qty_done, 0.0)
move_line.qty_done = 100.0
@@ -258,7 +258,7 @@ class StockMove(TransactionCase):
# fill the move line
move_line = move1.move_line_ids[0]
self.assertEqual(move_line.product_qty, 100.0)
self.assertEqual(move_line.reserved_qty, 100.0)
self.assertEqual(move_line.qty_done, 0.0)
move_line.qty_done = 100.0
@@ -333,7 +333,7 @@ class StockMove(TransactionCase):
move1._action_assign()
self.assertEqual(len(move1.move_line_ids), 4)
for ml in move1.move_line_ids:
self.assertEqual(ml.product_qty, 1.0)
self.assertEqual(ml.reserved_qty, 1.0)
# assign lot3 and lot 4 to both untracked move lines
lot3 = self.env['stock.lot'].create({
@@ -350,7 +350,7 @@ class StockMove(TransactionCase):
untracked_move_line[0].lot_id = lot3
untracked_move_line[1].lot_id = lot4
for ml in move1.move_line_ids:
self.assertEqual(ml.product_qty, 1.0)
self.assertEqual(ml.reserved_qty, 1.0)
# no changes on quants, even if i made some move lines with a lot id whom reserved on untracked quants
self.assertEqual(len(self.gather_relevant(self.product_serial, self.stock_location, strict=True)), 1.0) # with a qty of 2
@@ -559,9 +559,9 @@ class StockMove(TransactionCase):
move_line = move1.move_line_ids
move_line.lot_id = lot1
self.assertEqual(move_line.product_qty, 1.0)
self.assertEqual(move_line.reserved_qty, 1.0)
move_line.lot_id = lot2
self.assertEqual(move_line.product_qty, 1.0)
self.assertEqual(move_line.reserved_qty, 1.0)
move_line.qty_done = 1
# validating the move line should move the lot, not create a negative quant in stock
@@ -602,11 +602,11 @@ class StockMove(TransactionCase):
move1._action_assign()
self.assertEqual(len(move1.move_line_ids), 2)
for ml in move1.move_line_ids:
self.assertEqual(ml.product_qty, 1.0)
self.assertEqual(ml.reserved_qty, 1.0)
untracked_move_line = move1.move_line_ids.filtered(lambda ml: not ml.lot_id).lot_id = lot2
for ml in move1.move_line_ids:
self.assertEqual(ml.product_qty, 1.0)
self.assertEqual(ml.reserved_qty, 1.0)
move1.move_line_ids.write({'qty_done': 1.0})
@@ -1879,7 +1879,7 @@ class StockMove(TransactionCase):
move_receipt.product_uom_qty = 3.0
move_receipt._action_assign()
self.assertEqual(move_receipt.state, 'assigned')
self.assertEqual(move_receipt.move_line_ids.product_uom_qty, 3)
self.assertEqual(move_receipt.move_line_ids.reserved_uom_qty, 3)
def test_unreserve_1(self):
""" Check that unreserving a stock move sets the products reserved as available and
@@ -2107,7 +2107,7 @@ class StockMove(TransactionCase):
move1._action_assign()
self.assertEqual(move1.state, 'assigned')
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.product_qty, 10)
self.assertEqual(move1.move_line_ids.reserved_qty, 10)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(q2.reserved_quantity, 20)
@@ -2171,7 +2171,7 @@ class StockMove(TransactionCase):
self.assertEqual(move1.state, 'confirmed')
self.assertEqual(len(move1.move_line_ids), 2)
self.assertEqual(move1.move_line_ids.mapped('qty_done'), [1, 1])
self.assertEqual(move1.move_line_ids.mapped('product_uom_qty'), [0, 0])
self.assertEqual(move1.move_line_ids.mapped('reserved_uom_qty'), [0, 0])
def test_link_assign_1(self):
""" Test the assignment mechanism when two chained stock moves try to move one unit of an
@@ -2330,7 +2330,7 @@ class StockMove(TransactionCase):
move_line_1 = move_pack_cust.move_line_ids[0]
self.assertEqual(move_line_1.location_id.id, self.pack_location.id)
self.assertEqual(move_line_1.location_dest_id.id, self.customer_location.id)
self.assertEqual(move_line_1.product_qty, 2.0)
self.assertEqual(move_line_1.reserved_qty, 2.0)
self.assertEqual(move_pack_cust.state, 'assigned')
def test_link_assign_4(self):
@@ -2397,7 +2397,7 @@ class StockMove(TransactionCase):
move_line_1 = move_pack_cust.move_line_ids[0]
self.assertEqual(move_line_1.location_id.id, self.pack_location.id)
self.assertEqual(move_line_1.location_dest_id.id, self.customer_location.id)
self.assertEqual(move_line_1.product_qty, 2.0)
self.assertEqual(move_line_1.reserved_qty, 2.0)
self.assertEqual(move_line_1.lot_id.id, lot1.id)
self.assertEqual(move_pack_cust.state, 'assigned')
@@ -2560,7 +2560,7 @@ class StockMove(TransactionCase):
'product_id': self.product.id,
'product_uom_id': self.uom_unit.id,
'qty_done': 6,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'lot_id': False,
'package_id': False,
'result_package_id': False,
@@ -2584,7 +2584,7 @@ class StockMove(TransactionCase):
move_pack_cust._action_assign()
self.assertEqual(move_pack_cust.state, 'partially_available')
move_line_pack_cust = move_pack_cust.move_line_ids
self.assertEqual(move_line_pack_cust.product_uom_qty, 6)
self.assertEqual(move_line_pack_cust.reserved_uom_qty, 6)
self.assertEqual(move_line_pack_cust.product_uom_id.id, self.uom_unit.id)
# move a dozen on the backorder to see how we handle the extra move
@@ -2593,7 +2593,7 @@ class StockMove(TransactionCase):
'product_id': self.product.id,
'product_uom_id': self.uom_dozen.id,
'qty_done': 1,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'lot_id': False,
'package_id': False,
'result_package_id': False,
@@ -2611,7 +2611,7 @@ class StockMove(TransactionCase):
# the second move should now be reservable
move_pack_cust._action_assign()
self.assertEqual(move_pack_cust.state, 'assigned')
self.assertEqual(move_line_pack_cust.product_uom_qty, 12)
self.assertEqual(move_line_pack_cust.reserved_uom_qty, 12)
self.assertEqual(move_line_pack_cust.product_uom_id.id, self.uom_unit.id)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, move_stock_pack.location_dest_id), 6)
@@ -2674,7 +2674,7 @@ class StockMove(TransactionCase):
picking_stock_pack.button_validate()
self.assertEqual(move_pack_cust.state, 'assigned')
for ml in move_pack_cust.move_line_ids:
self.assertEqual(ml.product_uom_qty, 1)
self.assertEqual(ml.reserved_uom_qty, 1)
self.assertEqual(ml.product_uom_id.id, self.uom_unit.id)
self.assertTrue(bool(ml.lot_id.id))
@@ -2756,7 +2756,7 @@ class StockMove(TransactionCase):
'product_id': self.product_serial.id,
'product_uom_id': self.uom_unit.id,
'qty_done': 1,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'lot_id': lot3.id,
'package_id': False,
'result_package_id': False,
@@ -2943,7 +2943,7 @@ class StockMove(TransactionCase):
'product_id': self.product.id,
'product_uom_id': self.uom_unit.id,
'qty_done': 1,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'lot_id': False,
'package_id': False,
'result_package_id': False,
@@ -3001,7 +3001,7 @@ class StockMove(TransactionCase):
'product_id': self.product.id,
'product_uom_id': self.uom_unit.id,
'qty_done': 1,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'lot_id': lot1.id,
'package_id': False,
'result_package_id': False,
@@ -3038,7 +3038,7 @@ class StockMove(TransactionCase):
'product_id': self.product.id,
'product_uom_id': self.uom_unit.id,
'qty_done': 2,
'product_uom_qty': 0,
'reserved_uom_qty': 0,
'lot_id': False,
'package_id': False,
'result_package_id': False,
@@ -3378,14 +3378,14 @@ class StockMove(TransactionCase):
self.assertEqual(move1.state, 'assigned')
self.assertEqual(len(move1.move_line_ids), 1)
move_line = move1.move_line_ids[0]
self.assertEqual(move_line.product_qty, 5)
self.assertEqual(move_line.reserved_qty, 5)
move_line.qty_done = 5.0
self.assertEqual(move_line.product_qty, 5) # don't change reservation
self.assertEqual(move_line.reserved_qty, 5) # don't change reservation
move_line.lot_id = lot1
self.assertEqual(move_line.product_qty, 5) # don't change reservation when assgning a lot now
self.assertEqual(move_line.reserved_qty, 5) # don't change reservation when assgning a lot now
move1._action_done()
self.assertEqual(move_line.product_qty, 0) # change reservation to 0 for done move
self.assertEqual(move_line.reserved_qty, 0) # change reservation to 0 for done move
self.assertEqual(move1.state, 'done')
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_lot, self.stock_location), 0.0)
@@ -3441,18 +3441,18 @@ class StockMove(TransactionCase):
else:
untracked_move_line = move_line
self.assertEqual(tracked_move_line.product_qty, 2)
self.assertEqual(tracked_move_line.reserved_qty, 2)
tracked_move_line.qty_done = 2
self.assertEqual(untracked_move_line.product_qty, 3)
self.assertEqual(untracked_move_line.reserved_qty, 3)
untracked_move_line.lot_id = lot2
self.assertEqual(untracked_move_line.product_qty, 3) # don't change reservation
self.assertEqual(untracked_move_line.reserved_qty, 3) # don't change reservation
untracked_move_line.qty_done = 3
self.assertEqual(untracked_move_line.product_qty, 3) # don't change reservation
self.assertEqual(untracked_move_line.reserved_qty, 3) # don't change reservation
move1._action_done()
self.assertEqual(untracked_move_line.product_qty, 0) # change reservation to 0 for done move
self.assertEqual(tracked_move_line.product_qty, 0) # change reservation to 0 for done move
self.assertEqual(untracked_move_line.reserved_qty, 0) # change reservation to 0 for done move
self.assertEqual(tracked_move_line.reserved_qty, 0) # change reservation to 0 for done move
self.assertEqual(move1.state, 'done')
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_lot, self.stock_location), 0.0)
@@ -4233,7 +4233,7 @@ class StockMove(TransactionCase):
picking.action_confirm()
for line in picking.move_line_ids:
line.qty_done = line.product_uom_qty
line.qty_done = line.reserved_uom_qty
return picking
@@ -5135,7 +5135,7 @@ class StockMove(TransactionCase):
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0)
self.assertEqual(len(picking.move_line_ids), 2)
unpacked_ml = picking.move_line_ids.filtered(lambda ml: not ml.result_package_id)
self.assertEqual(unpacked_ml.product_qty, 1)
self.assertEqual(unpacked_ml.reserved_qty, 1)
unpacked_ml.qty_done = 1
picking.action_put_in_pack()
self.assertEqual(len(picking.move_line_ids), 2)
+22 -22
View File
@@ -647,7 +647,7 @@ class TestPickShip(TestStockCommon):
backorder_wizard.process()
self.assertTrue(picking_client.move_line_ids, 'A move line should be created.')
self.assertEqual(picking_client.move_line_ids.product_uom_qty, 5, 'The move line should have 5 unit reserved.')
self.assertEqual(picking_client.move_line_ids.reserved_uom_qty, 5, 'The move line should have 5 unit reserved.')
# Directly delete the move lines on the picking. (Use show detail operation on picking type)
# Should do the same behavior than unreserve
@@ -769,24 +769,24 @@ class TestPickShip(TestStockCommon):
picking_pick.action_confirm()
picking_pick.action_assign()
for move_line in picking_pick.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
picking_pick._action_done()
picking_client.action_confirm()
picking_client.action_assign()
for move_line in picking_client.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
picking_client._action_done()
picking_pick, picking_client = self.create_pick_ship()
picking_pick.action_confirm()
picking_pick.action_assign()
for move_line in picking_pick.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
picking_pick._action_done()
picking_client.action_confirm()
picking_client.action_assign()
for move_line in picking_client.move_line_ids:
move_line.qty_done = move_line.product_uom_qty
move_line.qty_done = move_line.reserved_uom_qty
picking_client._action_done()
# Following FIFO strategy, First picking should have empty lot1 and took 3 of lot2.
@@ -804,9 +804,9 @@ class TestPickShip(TestStockCommon):
self.assertEqual(len(return_pick.move_line_ids), 2)
self.assertEqual(return_pick.move_line_ids[0].lot_id, lot2)
self.assertEqual(return_pick.move_line_ids[0].product_uom_qty, 4)
self.assertEqual(return_pick.move_line_ids[0].reserved_uom_qty, 4)
self.assertEqual(return_pick.move_line_ids[1].lot_id, lot3)
self.assertEqual(return_pick.move_line_ids[1].product_uom_qty, 6)
self.assertEqual(return_pick.move_line_ids[1].reserved_uom_qty, 6)
self.assertEqual(return_pick.picking_type_id, picking_client.location_id.warehouse_id.return_type_id)
class TestSinglePicking(TestStockCommon):
@@ -1021,7 +1021,7 @@ class TestSinglePicking(TestStockCommon):
self.assertEqual(move1.product_qty, 2.0)
self.assertEqual(move1.quantity_done, 2.0)
self.assertEqual(move1.reserved_availability, 0.0)
self.assertEqual(move1.move_line_ids.product_qty, 0.0) # change reservation to 0 for done move
self.assertEqual(move1.move_line_ids.reserved_qty, 0.0) # change reservation to 0 for done move
self.assertEqual(sum(move1.move_line_ids.mapped('qty_done')), 2.0)
self.assertEqual(move1.state, 'done')
@@ -1066,7 +1066,7 @@ class TestSinglePicking(TestStockCommon):
self.assertEqual(move1.product_qty, 3.0)
self.assertEqual(move1.quantity_done, 3.0)
self.assertEqual(move1.reserved_availability, 0.0)
self.assertEqual(move1.move_line_ids.product_qty, 0.0) # change reservation to 0 for done move
self.assertEqual(move1.move_line_ids.reserved_qty, 0.0) # change reservation to 0 for done move
self.assertEqual(sum(move1.move_line_ids.mapped('qty_done')), 3.0)
self.assertEqual(move1.state, 'done')
@@ -1103,7 +1103,7 @@ class TestSinglePicking(TestStockCommon):
self.assertEqual(move1.product_qty, 2.0)
self.assertEqual(move1.quantity_done, 2.0)
self.assertEqual(move1.reserved_availability, 0.0)
self.assertEqual(move1.move_line_ids.product_qty, 0.0) # change reservation to 0 for done move
self.assertEqual(move1.move_line_ids.reserved_qty, 0.0) # change reservation to 0 for done move
self.assertEqual(sum(move1.move_line_ids.mapped('qty_done')), 2.0)
self.assertEqual(move1.state, 'done')
@@ -1212,7 +1212,7 @@ class TestSinglePicking(TestStockCommon):
# Check reserved quantity
self.assertEqual(move1.reserved_availability, 1.0)
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.product_qty, 1)
self.assertEqual(move1.move_line_ids.reserved_qty, 1)
inventory_quant = self.env['stock.quant'].create({
'location_id': self.stock_location,
@@ -1227,7 +1227,7 @@ class TestSinglePicking(TestStockCommon):
# Check reserved quantity
self.assertEqual(move1.reserved_availability, 2.0)
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.product_qty, 2)
self.assertEqual(move1.move_line_ids.reserved_qty, 2)
def test_recheck_availability_2(self):
""" Same check than test_recheck_availability_1 but with lot this time.
@@ -1266,7 +1266,7 @@ class TestSinglePicking(TestStockCommon):
# Check reserved quantity
self.assertEqual(move1.reserved_availability, 1.0)
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.product_qty, 1)
self.assertEqual(move1.move_line_ids.reserved_qty, 1)
inventory_quant = self.env['stock.quant'].create({
'location_id': self.stock_location,
@@ -1283,7 +1283,7 @@ class TestSinglePicking(TestStockCommon):
self.assertEqual(move1.reserved_availability, 2.0)
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.lot_id.id, lot1.id)
self.assertEqual(move1.move_line_ids.product_qty, 2)
self.assertEqual(move1.move_line_ids.reserved_qty, 2)
def test_recheck_availability_3(self):
""" Same check than test_recheck_availability_2 but with different lots.
@@ -1324,7 +1324,7 @@ class TestSinglePicking(TestStockCommon):
# Check reserved quantity
self.assertEqual(move1.reserved_availability, 1.0)
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.product_qty, 1)
self.assertEqual(move1.move_line_ids.reserved_qty, 1)
inventory_quant = self.env['stock.quant'].create({
'location_id': self.stock_location,
@@ -1384,7 +1384,7 @@ class TestSinglePicking(TestStockCommon):
# Check reserved quantity
self.assertEqual(move1.reserved_availability, 1.0)
self.assertEqual(len(move1.move_line_ids), 1)
self.assertEqual(move1.move_line_ids.product_qty, 1)
self.assertEqual(move1.move_line_ids.reserved_qty, 1)
inventory_quant = self.env['stock.quant'].create({
'location_id': self.stock_location,
@@ -2273,9 +2273,9 @@ class TestStockUOM(TestStockCommon):
self.assertEqual(len(picking.move_line_ids), 1, 'One move line should exist for the picking.')
move_line = picking.move_line_ids
# check that we do not reserve more (in the same UOM) than the quantity in stock
self.assertEqual(float_compare(move_line.product_qty, quant.quantity, precision_digits=precision_digits), -1, "We do not reserve more (in the same UOM) than the quantity in stock")
self.assertEqual(float_compare(move_line.reserved_qty, quant.quantity, precision_digits=precision_digits), -1, "We do not reserve more (in the same UOM) than the quantity in stock")
# check that we reserve the same quantity in the ml and the quant
self.assertTrue(float_is_zero(move_line.product_qty - quant.reserved_quantity, precision_digits=precision_digits))
self.assertTrue(float_is_zero(move_line.reserved_qty - quant.reserved_quantity, precision_digits=precision_digits))
def test_update_product_move_line_with_different_uom(self):
""" Check that when the move line and corresponding
@@ -2375,9 +2375,9 @@ class TestStockUOM(TestStockCommon):
('lot_id', '=', quant_LtDA.lot_id.id),
('package_id', '=', quant_LtDA.package_id.id),
('owner_id', '=', quant_LtDA.owner_id.id),
('product_qty', '!=', 0)
('reserved_qty', '!=', 0)
])
reserved_on_move_lines_LtDA = sum(move_lines_LtDA.mapped('product_qty'))
reserved_on_move_lines_LtDA = sum(move_lines_LtDA.mapped('reserved_qty'))
move_lines_GtDA = self.env["stock.move.line"].search([
('product_id', '=', quant_GtDA.product_id.id),
@@ -2385,9 +2385,9 @@ class TestStockUOM(TestStockCommon):
('lot_id', '=', quant_GtDA.lot_id.id),
('package_id', '=', quant_GtDA.package_id.id),
('owner_id', '=', quant_GtDA.owner_id.id),
('product_qty', '!=', 0)
('reserved_qty', '!=', 0)
])
reserved_on_move_lines_GtDA = sum(move_lines_GtDA.mapped('product_qty'))
reserved_on_move_lines_GtDA = sum(move_lines_GtDA.mapped('reserved_qty'))
# check that we do not reserve more (in the same UOM) than the quantity in stock
self.assertEqual(float_compare(reserved_on_move_lines_LtDA, quant_LtDA.quantity, precision_digits=precision_digits), -1, "We do not reserve more (in the same UOM) than the quantity in stock")
+2 -2
View File
@@ -240,7 +240,7 @@ class TestPacking(TestPackingCommon):
picking.write({
'move_line_ids': [(0, 0, {
'product_id': self.productB.id,
'product_uom_qty': 7.0,
'reserved_uom_qty': 7.0,
'qty_done': 7.0,
'product_uom_id': self.productB.uom_id.id,
'location_id': self.customer_location.id,
@@ -252,7 +252,7 @@ class TestPacking(TestPackingCommon):
picking.write({
'move_line_ids': [(0, 0, {
'product_id': self.productA.id,
'product_uom_qty': 5.0,
'reserved_uom_qty': 5.0,
'qty_done': 5.0,
'product_uom_id': self.productA.uom_id.id,
'location_id': self.customer_location.id,
+1 -1
View File
@@ -118,7 +118,7 @@ class TestPackingNeg(TransactionCase):
for rec in delivery_order_neg.move_line_ids:
if rec.package_id.name == 'Palneg 1':
rec.qty_done = rec.product_qty
rec.qty_done = rec.reserved_qty
rec.result_package_id = False
elif rec.package_id.name == 'Palneg 2' and rec.lot_id.name == 'Lot neg':
rec.write({
+23 -23
View File
@@ -333,7 +333,7 @@ class TestStockFlow(TestStockCommon):
# Replace pack operation (Back order of Incoming shipment)
# ----------------------------------------------------------------------
packD = self.StockPackObj.search([('product_id', '=', self.productD.id), ('picking_id', '=', back_order_in.id)], order='product_qty')
packD = self.StockPackObj.search([('product_id', '=', self.productD.id), ('picking_id', '=', back_order_in.id)], order='reserved_qty')
self.assertEqual(len(packD), 1, 'Wrong number of pack operation.')
packD[0].write({
'qty_done': 8,
@@ -511,7 +511,7 @@ class TestStockFlow(TestStockCommon):
# ----------------------------------------------------
PackSdozAround = self.StockPackObj.search([('product_id', '=', self.SDozARound.id), ('picking_id', '=', picking_in_A.id)], limit=1)
self.assertEqual(PackSdozAround.product_qty, 11, 'Wrong quantity in pack operation (%s found instead of 11)' % (PackSdozAround.product_qty))
self.assertEqual(PackSdozAround.reserved_qty, 11, 'Wrong quantity in pack operation (%s found instead of 11)' % (PackSdozAround.reserved_qty))
res_dict = picking_in_A.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
wizard.process()
@@ -610,25 +610,25 @@ class TestStockFlow(TestStockCommon):
# Check pack operation quantity and unit of measure for product DozA.
PackdozA = self.StockPackObj.search([('product_id', '=', self.DozA.id), ('picking_id', '=', picking_in_B.id)], limit=1)
self.assertEqual(PackdozA.product_uom_qty, 120, 'Wrong quantity in pack operation (%s found instead of 120)' % (PackdozA.product_uom_qty))
self.assertEqual(PackdozA.product_qty, 10, 'Wrong real quantity in pack operation (%s found instead of 10)' % (PackdozA.product_qty))
self.assertEqual(PackdozA.reserved_uom_qty, 120, 'Wrong quantity in pack operation (%s found instead of 120)' % (PackdozA.reserved_uom_qty))
self.assertEqual(PackdozA.reserved_qty, 10, 'Wrong real quantity in pack operation (%s found instead of 10)' % (PackdozA.reserved_qty))
self.assertEqual(PackdozA.product_uom_id.id, self.uom_unit.id, 'Wrong uom in pack operation for product DozA.')
# Check pack operation quantity and unit of measure for product SDozA.
PackSdozA = self.StockPackObj.search([('product_id', '=', self.SDozA.id), ('picking_id', '=', picking_in_B.id)], limit=1)
self.assertEqual(PackSdozA.product_uom_qty, 1512, 'Wrong quantity in pack operation (%s found instead of 1512)' % (PackSdozA.product_uom_qty))
self.assertEqual(PackSdozA.reserved_uom_qty, 1512, 'Wrong quantity in pack operation (%s found instead of 1512)' % (PackSdozA.reserved_uom_qty))
self.assertEqual(PackSdozA.product_uom_id.id, self.uom_unit.id, 'Wrong uom in pack operation for product SDozA.')
# Check pack operation quantity and unit of measure for product SDozARound.
PackSdozAround = self.StockPackObj.search([('product_id', '=', self.SDozARound.id), ('picking_id', '=', picking_in_B.id)], limit=1)
self.assertEqual(PackSdozAround.product_uom_qty, 1584, 'Wrong quantity in pack operation (%s found instead of 1584)' % (PackSdozAround.product_uom_qty))
self.assertEqual(PackSdozAround.reserved_uom_qty, 1584, 'Wrong quantity in pack operation (%s found instead of 1584)' % (PackSdozAround.reserved_uom_qty))
self.assertEqual(PackSdozAround.product_uom_id.id, self.uom_unit.id, 'Wrong uom in pack operation for product SDozARound.')
# Check pack operation quantity and unit of measure for product gB.
packgB = self.StockPackObj.search([('product_id', '=', self.gB.id), ('picking_id', '=', picking_in_B.id)], limit=1)
self.assertEqual(packgB.product_uom_qty, 0.525, 'Wrong quantity in pack operation (%s found instead of 0.525)' % (packgB.product_uom_qty))
self.assertEqual(packgB.product_qty, 525, 'Wrong real quantity in pack operation (%s found instead of 525)' % (packgB.product_qty))
self.assertEqual(packgB.reserved_uom_qty, 0.525, 'Wrong quantity in pack operation (%s found instead of 0.525)' % (packgB.reserved_uom_qty))
self.assertEqual(packgB.reserved_qty, 525, 'Wrong real quantity in pack operation (%s found instead of 525)' % (packgB.reserved_qty))
self.assertEqual(packgB.product_uom_id.id, packgB.move_id.product_uom.id, 'Wrong uom in pack operation for product kgB.')
# Check pack operation quantity and unit of measure for product kgB.
packkgB = self.StockPackObj.search([('product_id', '=', self.kgB.id), ('picking_id', '=', picking_in_B.id)], limit=1)
self.assertEqual(packkgB.product_uom_qty, 20.0, 'Wrong quantity in pack operation (%s found instead of 20)' % (packkgB.product_uom_qty))
self.assertEqual(packkgB.reserved_uom_qty, 20.0, 'Wrong quantity in pack operation (%s found instead of 20)' % (packkgB.reserved_uom_qty))
self.assertEqual(packkgB.product_uom_id.id, self.uom_gm.id, 'Wrong uom in pack operation for product kgB')
# ----------------------------------------------------------------------
@@ -636,14 +636,14 @@ class TestStockFlow(TestStockCommon):
# ----------------------------------------------------------------------
self.StockPackObj.search([('product_id', '=', self.kgB.id), ('picking_id', '=', picking_in_B.id)]).write({
'product_uom_qty': 0.020, 'product_uom_id': self.uom_kg.id})
'reserved_uom_qty': 0.020, 'product_uom_id': self.uom_kg.id})
self.StockPackObj.search([('product_id', '=', self.gB.id), ('picking_id', '=', picking_in_B.id)]).write({
'product_uom_qty': 526, 'product_uom_id': self.uom_gm.id})
'reserved_uom_qty': 526, 'product_uom_id': self.uom_gm.id})
self.StockPackObj.search([('product_id', '=', self.DozA.id), ('picking_id', '=', picking_in_B.id)]).write({
'product_uom_qty': 4, 'product_uom_id': self.uom_dozen.id})
'reserved_uom_qty': 4, 'product_uom_id': self.uom_dozen.id})
self.StockPackObj.create({
'product_id': self.DozA.id,
'product_uom_qty': 48,
'reserved_uom_qty': 48,
'product_uom_id': self.uom_unit.id,
'location_id': self.supplier_location,
'location_dest_id': self.stock_location,
@@ -927,8 +927,8 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(move.state, 'assigned', 'Wrong state of move line.')
# Check pack operation quantity.
packKG = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', picking_in.id)], limit=1)
self.assertEqual(packKG.product_qty, 1000, 'Wrong product real quantity in pack operation (%s found instead of 1000)' % (packKG.product_qty))
self.assertEqual(packKG.product_uom_qty, 1, 'Wrong product quantity in pack operation (%s found instead of 1)' % (packKG.product_uom_qty))
self.assertEqual(packKG.reserved_qty, 1000, 'Wrong product real quantity in pack operation (%s found instead of 1000)' % (packKG.reserved_qty))
self.assertEqual(packKG.reserved_uom_qty, 1, 'Wrong product quantity in pack operation (%s found instead of 1)' % (packKG.reserved_uom_qty))
self.assertEqual(packKG.product_uom_id.id, self.uom_tone.id, 'Wrong product uom in pack operation.')
# Transfer Incoming shipment.
res_dict = picking_in.button_validate()
@@ -966,7 +966,7 @@ class TestStockFlow(TestStockCommon):
picking_out.action_confirm()
picking_out.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', picking_out.id)], limit=1)
pack_opt.write({'product_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 0.5})
res_dict = picking_out.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -990,7 +990,7 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_1.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_1.id)], limit=1)
pack_opt.write({'product_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 0.5})
res_dict = bo_out_1.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -1014,7 +1014,7 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_2.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_2.id)], limit=1)
pack_opt.write({'product_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 0.5})
res_dict = bo_out_2.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -1037,7 +1037,7 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_3.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_3.id)], limit=1)
pack_opt.write({'product_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 0.5})
res_dict = bo_out_3.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -1058,7 +1058,7 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_4.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_4.id)], limit=1)
pack_opt.write({'product_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 0.5})
res_dict = bo_out_4.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
wizard.process()
@@ -1327,7 +1327,7 @@ class TestStockFlow(TestStockCommon):
pack2 = pack_obj.create({'name': 'PACKINOUTTEST2'})
picking_in.move_line_ids[0].result_package_id = pack1
picking_in.move_line_ids[0].qty_done = 4
packop2 = picking_in.move_line_ids[0].with_context(bypass_reservation_update=True).copy({'product_uom_qty': 0})
packop2 = picking_in.move_line_ids[0].with_context(bypass_reservation_update=True).copy({'reserved_uom_qty': 0})
packop2.qty_done = 6
packop2.result_package_id = pack2
picking_in._action_done()
@@ -1351,7 +1351,7 @@ class TestStockFlow(TestStockCommon):
picking_out.action_confirm()
picking_out.action_assign()
packout1 = picking_out.move_line_ids[0]
packout2 = picking_out.move_line_ids[0].with_context(bypass_reservation_update=True).copy({'product_uom_qty': 0})
packout2 = picking_out.move_line_ids[0].with_context(bypass_reservation_update=True).copy({'reserved_uom_qty': 0})
packout1.qty_done = 2
packout1.package_id = pack1
packout2.package_id = pack2
@@ -1385,7 +1385,7 @@ class TestStockFlow(TestStockCommon):
pack2 = pack_obj.create({'name': 'PACKINOUTTEST2'})
picking_in.move_line_ids[0].result_package_id = pack1
picking_in.move_line_ids[0].qty_done = 120
packop2 = picking_in.move_line_ids[0].with_context(bypass_reservation_update=True).copy({'product_uom_qty': 0})
packop2 = picking_in.move_line_ids[0].with_context(bypass_reservation_update=True).copy({'reserved_uom_qty': 0})
packop2.qty_done = 80
packop2.result_package_id = pack2
picking_in._action_done()
+4 -4
View File
@@ -145,10 +145,10 @@ class TestWiseOperator(TransactionCase):
# put the move lines from delivery_order_wise2 into delivery_order_wise1
for pack_id2 in pack_ids2:
new_pack_id1 = pack_id2.copy(default={'picking_id': delivery_order_wise1.id, 'move_id': move1.id})
new_pack_id1.qty_done = pack_id2.product_qty
new_pack_id1.qty_done = pack_id2.reserved_qty
new_move_lines = delivery_order_wise1.move_line_ids.filtered(lambda p: p.qty_done)
self.assertEqual(sum(new_move_lines.mapped('product_qty')), 0)
self.assertEqual(sum(new_move_lines.mapped('reserved_qty')), 0)
self.assertEqual(sum(new_move_lines.mapped('qty_done')), 5)
self.assertEqual(set(new_move_lines.mapped('location_id.id')), set([
self.shelf1.id,
@@ -156,11 +156,11 @@ class TestWiseOperator(TransactionCase):
# put the move line from delivery_order_wise1 into delivery_order_wise2
new_pack_id2 = pack_ids1.copy(default={'picking_id': delivery_order_wise2.id, 'move_id': move2.id})
new_pack_id2.qty_done = pack_ids1.product_qty
new_pack_id2.qty_done = pack_ids1.reserved_qty
new_move_lines = delivery_order_wise2.move_line_ids.filtered(lambda p: p.qty_done)
self.assertEqual(len(new_move_lines), 1)
self.assertEqual(sum(new_move_lines.mapped('product_qty')), 0)
self.assertEqual(sum(new_move_lines.mapped('reserved_qty')), 0)
self.assertEqual(sum(new_move_lines.mapped('qty_done')), 5)
self.assertEqual(new_move_lines.location_id.id, self.shelf2.id)
+2 -2
View File
@@ -63,9 +63,9 @@
<field name="location_dest_id" options="{'no_create': True}" groups="stock.group_stock_multi_locations"/>
</group>
<group>
<label for="product_uom_qty" string="Quantity Reserved" attrs="{'invisible': [('state', '=', 'done')]}"/>
<label for="reserved_uom_qty" string="Quantity Reserved" attrs="{'invisible': [('state', '=', 'done')]}"/>
<div class="o_row" attrs="{'invisible': [('state', '=', 'done')]}">
<field name="product_uom_qty" readonly="1"/>
<field name="reserved_uom_qty" readonly="1"/>
<field name="product_uom_id" options="{'no_create': True}" string="Unit of Measure" groups="uom.group_uom"/>
</div>
<label for="qty_done" string="Quantity Done"/>
+5 -5
View File
@@ -207,7 +207,7 @@
<field name="model">stock.move.line</field>
<field name="priority">1000</field>
<field name="arch" type="xml">
<tree editable="bottom" decoration-muted="state == 'done' and is_locked == True" decoration-success="product_uom_qty==qty_done" decoration-danger="qty_done &gt; product_uom_qty and state != 'done' and picking_code != 'incoming'">
<tree editable="bottom" decoration-muted="state == 'done' and is_locked == True" decoration-success="reserved_uom_qty==qty_done" decoration-danger="qty_done &gt; reserved_uom_qty and state != 'done' and picking_code != 'incoming'">
<field name="company_id" invisible="1" force_save="1"/>
<field name="picking_id" invisible="1" force_save="1"/>
<field name="move_id" invisible="1" force_save="1" />
@@ -233,13 +233,13 @@
<field name="package_id" attrs="{'readonly': ['&amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}" invisible="not context.get('show_package')" groups="stock.group_tracking_lot"/>
<field name="result_package_id" attrs="{'readonly': ['&amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}" groups="stock.group_tracking_lot"/>
<field name="owner_id" attrs="{'readonly': ['&amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}" invisible="not context.get('show_owner')" groups="stock.group_tracking_owner"/>
<field name="product_uom_qty" invisible="not context.get('show_reserved_quantity')" readonly="1"/>
<field name="reserved_uom_qty" invisible="not context.get('show_reserved_quantity')" readonly="1"/>
<field name="state" invisible="1"/>
<field name="is_locked" invisible="1"/>
<field name="picking_code" invisible="1"/>
<field name="qty_done" attrs="{'readonly': ['|', '&amp;', ('state', '=', 'done'), ('is_locked', '=', True), '&amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True)]}"/>
<field name="product_uom_id" options="{'no_open': True, 'no_create': True}" string="Unit of Measure" groups="uom.group_uom"
attrs="{'readonly': ['|', '|', ('product_uom_qty', '!=', 0.0),
attrs="{'readonly': ['|', '|', ('reserved_uom_qty', '!=', 0.0),
'&amp;', ('package_level_id', '!=', False), ('parent.picking_type_entire_packs', '=', True),
'&amp;', ('state', '=', 'done'), ('id', '!=', False)]}"/>
</tree>
@@ -251,7 +251,7 @@
<field name="model">stock.move.line</field>
<field name="priority">1000</field>
<field name="arch" type="xml">
<tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)" decoration-danger="qty_done&gt;product_uom_qty and state!='done' and parent.picking_type_code != 'incoming'" decoration-success="qty_done==product_uom_qty and state!='done' and not result_package_id">
<tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)" decoration-danger="qty_done&gt;reserved_uom_qty and state!='done' and parent.picking_type_code != 'incoming'" decoration-success="qty_done==reserved_uom_qty and state!='done' and not result_package_id">
<field name="product_id" required="1" context="{'default_detailed_type': 'product'}" attrs="{'readonly': ['|', ('state', '=', 'done'), ('move_id', '!=', False)]}"/>
<field name="company_id" invisible="1"/>
<field name="move_id" invisible="1"/>
@@ -267,7 +267,7 @@
<field name="lot_id" groups="stock.group_production_lot" attrs="{'column_invisible': [('parent.show_lots_text', '=', True)], 'invisible': [('lots_visible', '=', False)]}" context="{'default_product_id': product_id, 'default_company_id': company_id, 'active_picking_id': picking_id}" optional="show"/>
<field name="lot_name" groups="stock.group_production_lot" attrs="{'column_invisible': [('parent.show_lots_text', '=', False)], 'invisible': [('lots_visible', '=', False)]}" context="{'default_product_id': product_id}"/>
<field name="is_initial_demand_editable" invisible="1"/>
<field name="product_uom_qty" readonly="1" attrs="{'column_invisible': ['|',('parent.immediate_transfer', '=', True),('parent.picking_type_code','=','incoming')]}" optional="show"/>
<field name="reserved_uom_qty" readonly="1" attrs="{'column_invisible': ['|',('parent.immediate_transfer', '=', True),('parent.picking_type_code','=','incoming')]}" optional="show"/>
<field name="is_locked" invisible="1"/>
<field name="qty_done" attrs="{'readonly': [('state', 'in', ('done', 'cancel')), ('is_locked', '=', True)]}" force_save="1"/>
<field name="product_uom_id" force_save="1" attrs="{'readonly': [('state', '!=', 'draft'), ('id', '!=', False)]}" groups="uom.group_uom"/>
@@ -35,9 +35,9 @@
<field name="lot_id" attrs="{'column_invisible': [('parent.show_lots_m2o', '=', False)]}" groups="stock.group_production_lot"/>
<field name="lot_name" attrs="{'column_invisible': [('parent.show_lots_text', '=', False)]}" groups="stock.group_production_lot"/>
<field name="owner_id" groups="stock.group_tracking_owner"/>
<field name="product_uom_qty"/>
<field name="reserved_uom_qty"/>
<field name="qty_done"/>
<field name="product_uom_id" options="{'no_open': True, 'no_create': True}" attrs="{'readonly': [('product_uom_qty', '!=', 0.0)]}" string="Unit of Measure" groups="uom.group_uom"/>
<field name="product_uom_id" options="{'no_open': True, 'no_create': True}" attrs="{'readonly': [('reserved_uom_qty', '!=', 0.0)]}" string="Unit of Measure" groups="uom.group_uom"/>
<field name="state" invisible="1"/>
</tree>
</field>
+1 -1
View File
@@ -82,7 +82,7 @@ class ReturnPicking(models.TransientModel):
if move.origin_returned_move_id and move.origin_returned_move_id != stock_move:
continue
if move.state in ('partially_available', 'assigned'):
quantity -= sum(move.move_line_ids.mapped('product_qty'))
quantity -= sum(move.move_line_ids.mapped('reserved_qty'))
elif move.state in ('done'):
quantity -= move.product_qty
quantity = float_round(quantity, precision_rounding=stock_move.product_id.uom_id.rounding)
@@ -108,7 +108,7 @@ class ValuationReconciliationTestCommon(AccountTestInvoicingCommon):
pickings.action_assign()
for picking in pickings:
for ml in picking.move_line_ids:
ml.qty_done = quantity or ml.product_qty
ml.qty_done = quantity or ml.reserved_qty
pickings._action_done()
self._change_pickings_date(pickings, date)
@@ -67,7 +67,7 @@ class StockMoveLine(models.Model):
picking_to_wave_vals['move_ids'] += [Command.link(move.id)]
continue
# Split the move
qty = sum(lines.mapped('product_qty'))
qty = sum(lines.mapped('reserved_qty'))
new_move = move._split(qty)
new_move[0]['move_line_ids'] = [Command.set(move_lines.ids)]
picking_to_wave_vals['move_ids'] += [Command.create(new_move[0])]
@@ -261,7 +261,7 @@ class StockPickingBatch(models.Model):
and not ml.result_package_id
)
if not move_line_ids:
move_line_ids = picking_move_lines.filtered(lambda ml: float_compare(ml.product_uom_qty, 0.0,
move_line_ids = picking_move_lines.filtered(lambda ml: float_compare(ml.reserved_uom_qty, 0.0,
precision_rounding=ml.product_uom_id.rounding) > 0 and float_compare(ml.qty_done, 0.0,
precision_rounding=ml.product_uom_id.rounding) == 0)
if move_line_ids:
@@ -92,7 +92,7 @@
<span t-esc="sum(move_operation.mapped('qty_done'))"/>
</t>
<t t-else="">
<span t-esc="sum(move_operation.mapped('product_uom_qty'))"/>
<span t-esc="sum(move_operation.mapped('reserved_uom_qty'))"/>
</t>
</t>
<t t-if="has_package">
@@ -68,7 +68,7 @@
<field name="location_dest_id"/>
<field name="package_id" groups="stock.group_tracking_lot"/>
<field name="result_package_id" groups="stock.group_tracking_lot"/>
<field name="product_uom_qty" readonly="1"/>
<field name="reserved_uom_qty" readonly="1"/>
<field name="product_uom_id" options="{'no_create': True}"
groups="uom.group_uom" readonly="1" force_save="1"/>
<field name="qty_done"/>