[REF] product_uom, *: clean quantity computation methods
product_uom._compute_quantity is an ensure one multi method taking a browse record as second paramter. It replaces _compute_qty and _compute_qty_obj to have a single and standard computation method.
This commit is contained in:
@@ -264,7 +264,6 @@ class DeliveryCarrier(models.Model):
|
||||
self.ensure_one()
|
||||
total = weight = volume = quantity = 0
|
||||
total_delivery = 0.0
|
||||
ProductUom = self.env['product.uom']
|
||||
for line in order.order_line:
|
||||
if line.state == 'cancel':
|
||||
continue
|
||||
@@ -272,7 +271,7 @@ class DeliveryCarrier(models.Model):
|
||||
total_delivery += line.price_total
|
||||
if not line.product_id or line.is_delivery:
|
||||
continue
|
||||
qty = ProductUom._compute_qty(line.product_uom.id, line.product_uom_qty, line.product_id.uom_id.id)
|
||||
qty = line.product_uom._compute_quantity(line.product_uom_qty, line.product_id.uom_id)
|
||||
weight += (line.product_id.weight or 0.0) * qty
|
||||
volume += (line.product_id.volume or 0.0) * qty
|
||||
quantity += qty
|
||||
|
||||
@@ -110,4 +110,4 @@ class SaleOrderLine(models.Model):
|
||||
for line in self:
|
||||
if not line.product_id or not line.product_uom or not line.product_uom_qty:
|
||||
return 0.0
|
||||
line.product_qty = self.env['product.uom']._compute_qty_obj(line.product_uom, line.product_uom_qty, line.product_id.uom_id)
|
||||
line.product_qty = line.product_uom._compute_quantity(line.product_uom_qty, line.product_id.uom_id)
|
||||
|
||||
@@ -68,10 +68,9 @@ class StockPicking(models.Model):
|
||||
@api.depends('pack_operation_ids')
|
||||
def _compute_bulk_weight(self):
|
||||
weight = 0.0
|
||||
uom_obj = self.env['product.uom']
|
||||
for packop in self.pack_operation_ids:
|
||||
if packop.product_id and not packop.result_package_id:
|
||||
weight += uom_obj._compute_qty_obj(packop.product_uom_id , packop.product_qty, packop.product_id.uom_id) * packop.product_id.weight
|
||||
weight += packop.product_uom_id._compute_quantity(packop.product_qty, packop.product_id.uom_id) * packop.product_id.weight
|
||||
self.weight_bulk = weight
|
||||
|
||||
@api.one
|
||||
|
||||
@@ -284,7 +284,7 @@ class Holidays(models.Model):
|
||||
uom_hour = resource.calendar_id.uom_id
|
||||
uom_day = self.env.ref('product.product_uom_day')
|
||||
if uom_hour and uom_day:
|
||||
return self.env['product.uom']._compute_qty_obj(uom_hour, hours, uom_day)
|
||||
return uom_hour._compute_quantity(hours, uom_day)
|
||||
|
||||
time_delta = to_dt - from_dt
|
||||
return math.ceil(time_delta.days + float(time_delta.seconds) / 86400)
|
||||
|
||||
@@ -248,7 +248,7 @@ class XmlDeclaration(models.TransientModel):
|
||||
else:
|
||||
amount = 0
|
||||
weight = (inv_line.product_id.weight or 0.0) * \
|
||||
self.env['product.uom']._compute_qty(inv_line.uom_id.id, inv_line.quantity, inv_line.product_id.uom_id.id)
|
||||
inv_line.uom_id._compute_quantity(inv_line.quantity, inv_line.product_id.uom_id)
|
||||
if not inv_line.product_id.uom_id.category_id:
|
||||
supply_units = inv_line.quantity
|
||||
else:
|
||||
|
||||
@@ -123,7 +123,7 @@ class MrpBom(models.Model):
|
||||
|
||||
bom = self._bom_find(product=current_line.product_id, picking_type=picking_type or self.picking_type_id, company_id=self.company_id.id)
|
||||
if bom.type == 'phantom':
|
||||
converted_line_quantity = self.env['product.uom']._compute_qty_obj(current_line.product_uom_id, line_quantity, bom.product_uom_id)
|
||||
converted_line_quantity = current_line.product_uom_id._compute_quantity(line_quantity, bom.product_uom_id)
|
||||
bom_lines = [(line, current_line.product_id, line_quantity) for line in bom.bom_line_ids] + bom_lines
|
||||
templates_done |= current_line.product_id.product_tmpl_id
|
||||
boms_done.append((bom, {'qty': converted_line_quantity, 'product': current_product, 'original_qty': quantity}))
|
||||
|
||||
@@ -262,7 +262,7 @@ class MrpProduction(models.Model):
|
||||
def _generate_moves(self):
|
||||
for production in self:
|
||||
production._generate_finished_moves()
|
||||
factor = self.env['product.uom']._compute_qty(production.product_uom_id.id, production.product_qty, production.bom_id.product_uom_id.id)
|
||||
factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id)
|
||||
boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
|
||||
production._generate_raw_moves(lines)
|
||||
# Check for all draft moves whether they are mto or not
|
||||
@@ -306,7 +306,7 @@ class MrpProduction(models.Model):
|
||||
source_location = self.bom_id.routing_id.location_id
|
||||
else:
|
||||
source_location = self.location_src_id
|
||||
original_quantity = self.env['product.uom']._compute_qty(self.product_uom_id.id, self.product_qty, self.bom_id.product_uom_id.id)
|
||||
original_quantity = self.product_uom_id._compute_quantity(self.product_qty, self.bom_id.product_uom_id)
|
||||
|
||||
data = {
|
||||
'name': self.name,
|
||||
@@ -369,9 +369,8 @@ class MrpProduction(models.Model):
|
||||
def button_plan(self):
|
||||
""" Create work orders. And probably do stuff, like things. """
|
||||
orders_to_plan = self.filtered(lambda order: order.routing_id and order.state == 'confirmed')
|
||||
UoM = self.env['product.uom']
|
||||
for order in orders_to_plan:
|
||||
quantity = UoM._compute_qty_obj(order.product_uom_id, order.product_qty, order.bom_id.product_uom_id)
|
||||
quantity = order.product_uom_id._compute_quantity(order.product_qty, order.bom_id.product_uom_id)
|
||||
boms, lines = order.bom_id.explode(order.product_id, quantity, picking_type=order.bom_id.picking_type_id)
|
||||
order._generate_workorders(boms)
|
||||
orders_to_plan.write({'state': 'planned'})
|
||||
|
||||
@@ -153,7 +153,7 @@ class MrpUnbuild(models.Model):
|
||||
def _generate_produce_moves(self):
|
||||
moves = self.env['stock.move']
|
||||
for unbuild in self:
|
||||
factor = self.env['product.uom']._compute_qty(unbuild.product_uom_id.id, unbuild.product_qty, unbuild.bom_id.product_uom_id.id)
|
||||
factor = unbuild.product_uom_id._compute_quantity(unbuild.product_qty, unbuild.bom_id.product_uom_id)
|
||||
boms, lines = unbuild.bom_id.explode(unbuild.product_id, factor / unbuild.bom_id.product_qty, picking_type=unbuild.bom_id.picking_type_id)
|
||||
for line, line_data in lines:
|
||||
moves += unbuild._generate_move_from_bom_line(line, line_data['qty'])
|
||||
|
||||
@@ -129,7 +129,6 @@ class StockMove(models.Model):
|
||||
@api.multi
|
||||
def create_lots(self):
|
||||
lots = self.env['stock.move.lots']
|
||||
uom_obj = self.env['product.uom']
|
||||
for move in self:
|
||||
unlink_move_lots = move.move_lot_ids.filtered(lambda x : (x.quantity_done == 0) and not x.workorder_id)
|
||||
unlink_move_lots.unlink()
|
||||
@@ -140,7 +139,7 @@ class StockMove(models.Model):
|
||||
old_move_lot.setdefault(key, []).append(movelot)
|
||||
for quant in move.reserved_quant_ids:
|
||||
key = (quant.lot_id.id or False)
|
||||
quantity = uom_obj._compute_qty(move.product_id.uom_id.id, quant.qty, move.product_uom.id)
|
||||
quantity = move.product_id.uom_id._compute_quantity(quant.qty, move.product_uom)
|
||||
if group_new_quant.get(key):
|
||||
group_new_quant[key] += quantity
|
||||
else:
|
||||
@@ -170,7 +169,6 @@ class StockMove(models.Model):
|
||||
moves = self._filter_closed_moves()
|
||||
quant_obj = self.env['stock.quant']
|
||||
moves_todo = self.env['stock.move']
|
||||
uom_obj = self.env['product.uom']
|
||||
for move in moves:
|
||||
rounding = move.product_uom.rounding
|
||||
if float_compare(move.quantity_done, 0.0, precision_rounding=rounding) <= 0:
|
||||
@@ -186,7 +184,7 @@ class StockMove(models.Model):
|
||||
for move in moves_todo:
|
||||
if float_compare(move.quantity_done, move.product_uom_qty, precision_rounding=rounding):
|
||||
# Need to do some kind of conversion here
|
||||
qty_split = uom_obj._compute_qty(move.product_uom.id, move.product_uom_qty - move.quantity_done, move.product_id.uom_id.id)
|
||||
qty_split = move.product_uom._compute_quantity(move.product_uom_qty - move.quantity_done, move.product_id.uom_id)
|
||||
new_move = move.split(qty_split)
|
||||
self.browse(new_move).quantity_done = 0.0
|
||||
main_domain = [('qty', '>', 0)]
|
||||
@@ -200,7 +198,7 @@ class StockMove(models.Model):
|
||||
else:
|
||||
for movelot in move.move_lot_ids:
|
||||
if float_compare(movelot.quantity_done, 0, precision_rounding=rounding) > 0:
|
||||
qty = uom_obj._compute_qty(move.product_uom.id, movelot.quantity_done, move.product_id.uom_id.id)
|
||||
qty = move.product_uom._compute_quantity(movelot.quantity_done, move.product_id.uom_id)
|
||||
quants = quant_obj.quants_get_preferred_domain(qty, move, lot_id=movelot.lot_id.id, domain=main_domain, preferred_domain_list=preferred_domain_list)
|
||||
self.env['stock.quant'].quants_move(quants, move, move.location_dest_id, lot_id = movelot.lot_id.id)
|
||||
move.quants_unreserve()
|
||||
@@ -273,7 +271,7 @@ class StockMove(models.Model):
|
||||
return self
|
||||
phantom_moves = self.env['stock.move']
|
||||
processed_moves = self.env['stock.move']
|
||||
factor = self.env['product.uom']._compute_qty(self.product_uom.id, self.product_uom_qty, bom.product_uom_id.id) / bom.product_qty
|
||||
factor = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id) / bom.product_qty
|
||||
boms, lines = bom.sudo().explode(self.product_id, factor, picking_type=bom.picking_type_id)
|
||||
for bom_line, line_data in lines:
|
||||
phantom_moves += self._generate_move_phantom(bom_line, line_data['qty'])
|
||||
|
||||
@@ -42,13 +42,12 @@ class StockMoveConsume(models.TransientModel):
|
||||
|
||||
@api.multi
|
||||
def do_move_consume(self):
|
||||
UoM = self.env['product.uom']
|
||||
Production = self.env['mrp.production']
|
||||
|
||||
move = self.env['stock.move'].browse(self._context['active_id'])
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
for wizard in self:
|
||||
qty = UoM._compute_qty(wizard.product_uom.id, wizard.product_qty, wizard.product_id.uom_id.id)
|
||||
qty = wizard.product_uom._compute_quantity(wizard.product_qty, wizard.product_id.uom_id)
|
||||
remaining_qty = move.product_qty - qty
|
||||
# check for product quantity is less than previously planned
|
||||
if float_compare(remaining_qty, 0, precision_digits=precision) >= 0:
|
||||
|
||||
@@ -17,11 +17,10 @@ class Production(models.Model):
|
||||
# TDE FIXME: was action_confirm ?? -> refactored
|
||||
Move = self.env['stock.move']
|
||||
res = super(Production, self)._generate_moves()
|
||||
UoM = self.env['product.uom']
|
||||
for production in self.filtered(lambda production: production.bom_id):
|
||||
source = production.product_id.property_stock_production.id
|
||||
for sub_product in production.bom_id.sub_products:
|
||||
product_uom_factor = UoM._compute_qty_obj(production.product_uom_id, production.product_qty, production.bom_id.product_uom_id)
|
||||
product_uom_factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id)
|
||||
qty1 = sub_product.product_qty
|
||||
qty1 *= product_uom_factor / production.bom_id.product_qty
|
||||
data = {
|
||||
|
||||
@@ -280,7 +280,7 @@ class product_product(osv.osv):
|
||||
# Set quantity in UoM of seller
|
||||
quantity_uom_seller = quantity
|
||||
if quantity_uom_seller and uom_id and uom_id != seller.product_uom:
|
||||
quantity_uom_seller = uom_id._compute_qty_obj(uom_id, quantity_uom_seller, seller.product_uom)
|
||||
quantity_uom_seller = uom_id._compute_quantity(quantity_uom_seller, seller.product_uom)
|
||||
|
||||
if seller.date_start and seller.date_start > date:
|
||||
continue
|
||||
|
||||
@@ -177,8 +177,8 @@ class product_pricelist(osv.osv):
|
||||
qty_in_product_uom = qty
|
||||
if qty_uom_id != product.uom_id.id:
|
||||
try:
|
||||
qty_in_product_uom = product_uom_obj._compute_qty(
|
||||
cr, uid, context['uom'], qty, product.uom_id.id)
|
||||
qty_in_product_uom = product_uom_obj._compute_quantity(
|
||||
cr, uid, [context['uom']], qty, product.uom_id)
|
||||
except UserError:
|
||||
# Ignored - incompatible UoM in context, use default product UoM
|
||||
pass
|
||||
|
||||
@@ -101,26 +101,15 @@ class product_uom(osv.osv):
|
||||
('factor_gt_zero', 'CHECK (factor!=0)', 'The conversion ratio for a unit of measure cannot be 0!')
|
||||
]
|
||||
|
||||
@api.cr_uid
|
||||
def _compute_qty(self, cr, uid, from_uom_id, qty, to_uom_id=False, round=True, rounding_method='UP'):
|
||||
if not from_uom_id or not qty or not to_uom_id:
|
||||
return qty
|
||||
uoms = self.browse(cr, uid, [from_uom_id, to_uom_id])
|
||||
if uoms[0].id == from_uom_id:
|
||||
from_unit, to_unit = uoms[0], uoms[-1]
|
||||
else:
|
||||
from_unit, to_unit = uoms[-1], uoms[0]
|
||||
return self._compute_qty_obj(cr, uid, from_unit, qty, to_unit, round=round, rounding_method=rounding_method)
|
||||
|
||||
def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, round=True, rounding_method='UP', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
def _compute_quantity(self, cr, uid, ids, qty, to_unit, round=True, rounding_method='UP', context=None):
|
||||
context = context if context is not None else {}
|
||||
from_unit = self.browse(cr, uid, ids[0], context=context)
|
||||
if from_unit.category_id.id != to_unit.category_id.id:
|
||||
if context.get('raise-exception', True):
|
||||
raise UserError(_('Conversion from Product UoM %s to Default UoM %s is not possible as they both belong to different Category!.') % (from_unit.name,to_unit.name))
|
||||
else:
|
||||
return qty
|
||||
amount = qty/from_unit.factor
|
||||
amount = qty / from_unit.factor
|
||||
if to_unit:
|
||||
amount = amount * to_unit.factor
|
||||
if round:
|
||||
|
||||
@@ -13,12 +13,14 @@ class TestUom(TransactionCase):
|
||||
cr, uid = self.cr, self.uid
|
||||
gram_id = self.imd.get_object_reference(cr, uid, 'product', 'product_uom_gram')[1]
|
||||
kg_id = self.imd.get_object_reference(cr, uid, 'product', 'product_uom_kgm')[1]
|
||||
kg = self.registry['product.uom'].browse(cr, uid, [kg_id])
|
||||
tonne_id = self.imd.get_object_reference(cr, uid, 'product', 'product_uom_ton')[1]
|
||||
tonne = self.registry['product.uom'].browse(cr, uid, [tonne_id])
|
||||
unit_id = self.imd.get_object_reference(cr, uid, 'product','product_uom_unit')[1]
|
||||
unit = self.registry['product.uom'].browse(cr, uid, [unit_id])
|
||||
dozen_id = self.imd.get_object_reference(cr, uid, 'product','product_uom_dozen')[1]
|
||||
|
||||
qty = self.uom._compute_qty(cr, uid, gram_id, 1020000, tonne_id)
|
||||
qty = self.uom._compute_quantity(cr, uid, [gram_id], 1020000, tonne)
|
||||
self.assertEquals(qty, 1.02, "Converted quantity does not correspond.")
|
||||
|
||||
price = self.uom._compute_price(cr, uid, [gram_id], 2, tonne)
|
||||
@@ -29,13 +31,13 @@ class TestUom(TransactionCase):
|
||||
# and the Unit rounding will round that up to 13.
|
||||
# This is a partial regression test for rev. 311c77bb, which is further improved
|
||||
# by rev. fa2f7b86.
|
||||
qty = self.uom._compute_qty(cr, uid, dozen_id, 1, unit_id)
|
||||
qty = self.uom._compute_quantity(cr, uid, [dozen_id], 1, unit)
|
||||
self.assertEquals(qty, 12.0, "Converted quantity does not correspond.")
|
||||
|
||||
# Regression test for side-effect of commit 311c77bb - converting 1234 Grams
|
||||
# into Kilograms should work even if grams are rounded to 1.
|
||||
self.uom.write(cr, uid, gram_id, {'rounding': 1})
|
||||
qty = self.uom._compute_qty(cr, uid, gram_id, 1234, kg_id)
|
||||
qty = self.uom._compute_quantity(cr, uid, [gram_id], 1234, kg)
|
||||
self.assertEquals(qty, 1.234, "Converted quantity does not correspond.")
|
||||
|
||||
def test_20_rounding(self):
|
||||
@@ -50,6 +52,7 @@ class TestUom(TransactionCase):
|
||||
'rounding': 1.0,
|
||||
'category_id': categ_unit_id
|
||||
})
|
||||
score = self.uom.browse(cr, uid, score_id)
|
||||
|
||||
qty = self.uom._compute_qty(cr, uid, unit_id, 2, score_id)
|
||||
qty = self.uom._compute_quantity(cr, uid, [unit_id], 2, score)
|
||||
self.assertEquals(qty, 1, "Converted quantity should be rounded up.")
|
||||
|
||||
@@ -502,12 +502,11 @@ class PurchaseOrderLine(models.Model):
|
||||
qty = 0.0
|
||||
for inv_line in line.invoice_lines:
|
||||
if inv_line.invoice_id.state not in ['cancel']:
|
||||
qty += inv_line.uom_id._compute_qty_obj(inv_line.uom_id, inv_line.quantity, line.product_uom)
|
||||
qty += inv_line.uom_id._compute_quantity(inv_line.quantity, line.product_uom)
|
||||
line.qty_invoiced = qty
|
||||
|
||||
@api.depends('order_id.state', 'move_ids.state')
|
||||
def _compute_qty_received(self):
|
||||
productuom = self.env['product.uom']
|
||||
for line in self:
|
||||
if line.order_id.state not in ['purchase', 'done']:
|
||||
line.qty_received = 0.0
|
||||
@@ -519,7 +518,7 @@ class PurchaseOrderLine(models.Model):
|
||||
for move in line.move_ids:
|
||||
if move.state == 'done':
|
||||
if move.product_uom != line.product_uom:
|
||||
total += productuom._compute_qty_obj(move.product_uom, move.product_uom_qty, line.product_uom)
|
||||
total += move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
|
||||
else:
|
||||
total += move.product_uom_qty
|
||||
line.qty_received = total
|
||||
@@ -601,7 +600,7 @@ class PurchaseOrderLine(models.Model):
|
||||
# Fullfill all related procurements with this po line
|
||||
diff_quantity = line.product_qty
|
||||
for procurement in line.procurement_ids:
|
||||
procurement_qty = procurement.product_uom._compute_qty_obj(procurement.product_uom, procurement.product_qty, line.product_uom)
|
||||
procurement_qty = procurement.product_uom._compute_quantity(procurement.product_qty, line.product_uom)
|
||||
tmp = template.copy()
|
||||
tmp.update({
|
||||
'product_uom_qty': min(procurement_qty, diff_quantity),
|
||||
@@ -767,7 +766,7 @@ class ProcurementOrder(models.Model):
|
||||
others_procs = procurement.purchase_line_id.procurement_ids.filtered(lambda r: r != procurement)
|
||||
for other_proc in others_procs:
|
||||
if other_proc.state not in ['cancel', 'draft']:
|
||||
product_qty += other_proc.product_uom._compute_qty_obj(other_proc.product_uom, other_proc.product_qty, procurement.purchase_line_id.product_uom)
|
||||
product_qty += other_proc.product_uom._compute_quantity(other_proc.product_qty, procurement.purchase_line_id.product_uom)
|
||||
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
if not float_is_zero(product_qty, precision_digits=precision):
|
||||
@@ -823,7 +822,7 @@ class ProcurementOrder(models.Model):
|
||||
def _prepare_purchase_order_line(self, po, supplier):
|
||||
self.ensure_one()
|
||||
|
||||
procurement_uom_po_qty = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_qty, self.product_id.uom_po_id)
|
||||
procurement_uom_po_qty = self.product_uom._compute_quantity(self.product_qty, self.product_id.uom_po_id)
|
||||
seller = self.product_id._select_seller(
|
||||
partner_id=supplier.name,
|
||||
quantity=procurement_uom_po_qty,
|
||||
@@ -943,7 +942,7 @@ class ProcurementOrder(models.Model):
|
||||
po_line = False
|
||||
for line in po.order_line:
|
||||
if line.product_id == procurement.product_id and line.product_uom == procurement.product_id.uom_po_id:
|
||||
procurement_uom_po_qty = self.env['product.uom']._compute_qty_obj(procurement.product_uom, procurement.product_qty, procurement.product_id.uom_po_id)
|
||||
procurement_uom_po_qty = procurement.product_uom._compute_quantity(procurement.product_qty, procurement.product_id.uom_po_id)
|
||||
seller = procurement.product_id._select_seller(
|
||||
partner_id=partner,
|
||||
quantity=line.product_qty + procurement_uom_po_qty,
|
||||
|
||||
@@ -27,12 +27,12 @@ class PurchaseOrderLine(models.Model):
|
||||
bom_delivered = {}
|
||||
if bom:
|
||||
bom_delivered[bom.id] = False
|
||||
product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_qty, bom.product_uom_id)
|
||||
product_uom_qty_bom = self.product_uom._compute_quantity(self.product_qty, bom.product_uom_id)
|
||||
boms, lines = bom.explode(self.product_id, product_uom_qty_bom)
|
||||
for bom_line, data in lines:
|
||||
qty = 0.0
|
||||
for move in self.move_ids.filtered(lambda x: x.state == 'done' and x.product_id == bom_line.product_id):
|
||||
qty += self.env['product.uom']._compute_qty(move.product_uom.id, move.product_uom_qty, bom_line.product_uom_id.id)
|
||||
qty += move.product_uom._compute_quantity(move.product_uom_qty, bom_line.product_uom_id)
|
||||
if float_compare(qty, data['qty'], precision_digits=precision) < 0:
|
||||
bom_delivered[bom.id] = False
|
||||
break
|
||||
|
||||
@@ -118,13 +118,12 @@ class PurchaseRequisitionLine(models.Model):
|
||||
@api.multi
|
||||
@api.depends('requisition_id.purchase_ids.state')
|
||||
def _compute_ordered_qty(self):
|
||||
ProductUOM = self.env['product.uom']
|
||||
for line in self:
|
||||
total = 0.0
|
||||
for po in line.requisition_id.purchase_ids.filtered(lambda purchase_order: purchase_order.state in ['purchase', 'done']):
|
||||
for po_line in po.order_line.filtered(lambda order_line: order_line.product_id == line.product_id):
|
||||
if po_line.product_uom != line.product_uom_id:
|
||||
total += ProductUOM._compute_qty_obj(po_line.product_uom, po_line.product_qty, line.product_uom_id)
|
||||
total += po_line.product_uom._compute_quantity(po_line.product_qty, line.product_uom_id)
|
||||
else:
|
||||
total += po_line.product_qty
|
||||
line.qty_ordered = total
|
||||
@@ -199,9 +198,7 @@ class PurchaseOrder(models.Model):
|
||||
product_qty = 0
|
||||
price_unit = line.price_unit
|
||||
elif line.product_uom_id != line.product_id.uom_po_id:
|
||||
ProductUOM = self.env['product.uom']
|
||||
product_qty = ProductUOM._compute_qty_obj(
|
||||
line.product_uom_id, line.product_qty, line.product_id.uom_po_id)
|
||||
product_qty = line.product_uom_id._compute_quantity(line.product_qty, line.product_id.uom_po_id)
|
||||
price_unit = line.product_uom_id._compute_price(line.price_unit, line.product_id.uom_po_id)
|
||||
else:
|
||||
product_qty = line.product_qty
|
||||
|
||||
+2
-2
@@ -615,9 +615,9 @@ class SaleOrderLine(models.Model):
|
||||
for invoice_line in line.invoice_lines:
|
||||
if invoice_line.invoice_id.state != 'cancel':
|
||||
if invoice_line.invoice_id.type == 'out_invoice':
|
||||
qty_invoiced += self.env['product.uom']._compute_qty_obj(invoice_line.uom_id, invoice_line.quantity, line.product_uom)
|
||||
qty_invoiced += invoice_line.uom_id._compute_quantity(invoice_line.quantity, line.product_uom)
|
||||
elif invoice_line.invoice_id.type == 'out_refund':
|
||||
qty_invoiced -= self.env['product.uom']._compute_qty_obj(invoice_line.uom_id, invoice_line.quantity, line.product_uom)
|
||||
qty_invoiced -= invoice_line.uom_id._compute_quantity(invoice_line.quantity, line.product_uom)
|
||||
line.qty_invoiced = qty_invoiced
|
||||
|
||||
@api.depends('price_unit', 'discount')
|
||||
|
||||
@@ -25,7 +25,7 @@ class SaleOrderLine(models.Model):
|
||||
lines.setdefault(line, 0.0)
|
||||
uom = self.env['product.uom'].browse(d['product_uom_id'][0])
|
||||
if line.product_uom.category_id == uom.category_id:
|
||||
qty = self.env['product.uom']._compute_qty_obj(uom, d['unit_amount'], line.product_uom)
|
||||
qty = uom._compute_quantity(d['unit_amount'], line.product_uom)
|
||||
else:
|
||||
qty = d['unit_amount']
|
||||
lines[line] += qty
|
||||
|
||||
@@ -38,13 +38,13 @@ class SaleOrderLine(models.Model):
|
||||
bom = self.env['mrp.bom']._bom_find(product=self.product_id)
|
||||
if bom and bom.type == 'phantom':
|
||||
bom_delivered[bom.id] = False
|
||||
product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, bom.product_uom_id)
|
||||
product_uom_qty_bom = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id)
|
||||
boms, lines = bom.explode(self.product_id, product_uom_qty_bom)
|
||||
for bom_line, data in lines:
|
||||
qty = 0.0
|
||||
for move in self.procurement_ids.mapped('move_ids'):
|
||||
if move.state == 'done' and move.product_id.id == bom_line.product_id.id:
|
||||
qty += self.env['product.uom']._compute_qty(move.product_uom.id, move.product_uom_qty, bom_line.product_uom_id.id)
|
||||
qty += move.product_uom._compute_quantity(move.product_uom_qty, bom_line.product_uom_id)
|
||||
if float_compare(qty, data['qty'], precision_digits=precision) < 0:
|
||||
bom_delivered[bom.id] = False
|
||||
break
|
||||
@@ -65,12 +65,11 @@ class AccountInvoiceLine(models.Model):
|
||||
price_unit = super(AccountInvoiceLine, self)._get_anglo_saxon_price_unit()
|
||||
# in case of anglo saxon with a product configured as invoiced based on delivery, with perpetual
|
||||
# valuation and real price costing method, we must find the real price for the cost of good sold
|
||||
uom_obj = self.env['product.uom']
|
||||
if self.product_id.invoice_policy == "delivery":
|
||||
for s_line in self.sale_line_ids:
|
||||
# qtys already invoiced
|
||||
qty_done = sum([uom_obj._compute_qty_obj(x.uom_id, x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
|
||||
quantity = uom_obj._compute_qty_obj(self.uom_id, self.quantity, self.product_id.uom_id)
|
||||
qty_done = sum([x.uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
|
||||
quantity = self.uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
|
||||
# Put moves in fixed order by date executed
|
||||
moves = self.env['stock.move']
|
||||
for procurement in s_line.procurement_ids:
|
||||
@@ -90,5 +89,5 @@ class AccountInvoiceLine(models.Model):
|
||||
prod_quantity = factor * quantity
|
||||
average_price_unit += self._compute_average_price(prod_qty_done, prod_quantity, prod_moves)
|
||||
price_unit = average_price_unit or price_unit
|
||||
price_unit = uom_obj._compute_qty_obj(self.uom_id, price_unit, self.product_id.uom_id, round=False)
|
||||
price_unit = self.uom_id._compute_quantity(price_unit, self.product_id.uom_id, round=False)
|
||||
return price_unit
|
||||
|
||||
@@ -19,12 +19,11 @@ class AccountInvoiceLine(models.Model):
|
||||
price_unit = super(AccountInvoiceLine,self)._get_anglo_saxon_price_unit()
|
||||
# in case of anglo saxon with a product configured as invoiced based on delivery, with perpetual
|
||||
# valuation and real price costing method, we must find the real price for the cost of good sold
|
||||
uom_obj = self.env['product.uom']
|
||||
if self.product_id.invoice_policy == "delivery":
|
||||
for s_line in self.sale_line_ids:
|
||||
# qtys already invoiced
|
||||
qty_done = sum([uom_obj._compute_qty_obj(x.uom_id, x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
|
||||
quantity = uom_obj._compute_qty_obj(self.uom_id, self.quantity, self.product_id.uom_id)
|
||||
qty_done = sum([x.uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
|
||||
quantity = self.uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
|
||||
# Put moves in fixed order by date executed
|
||||
moves = self.env['stock.move']
|
||||
for procurement in s_line.procurement_ids:
|
||||
@@ -35,7 +34,7 @@ class AccountInvoiceLine(models.Model):
|
||||
# on the moves we encounter.
|
||||
average_price_unit = self._compute_average_price(qty_done, quantity, moves)
|
||||
price_unit = average_price_unit or price_unit
|
||||
price_unit = uom_obj._compute_qty_obj(self.uom_id, price_unit, self.product_id.uom_id, round=False)
|
||||
price_unit = self.uom_id._compute_quantity(price_unit, self.product_id.uom_id, round=False)
|
||||
return price_unit
|
||||
|
||||
def _compute_average_price(self, qty_done, quantity, moves):
|
||||
|
||||
@@ -137,7 +137,7 @@ class SaleOrderLine(models.Model):
|
||||
return {}
|
||||
if self.product_id.type == 'product':
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
product_qty = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, self.product_id.uom_id)
|
||||
product_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id)
|
||||
if float_compare(self.product_id.virtual_available, product_qty, precision_digits=precision) == -1:
|
||||
is_available = self._check_routing()
|
||||
if not is_available:
|
||||
@@ -183,9 +183,9 @@ class SaleOrderLine(models.Model):
|
||||
qty = 0.0
|
||||
for move in self.procurement_ids.mapped('move_ids').filtered(lambda r: r.state == 'done' and not r.scrapped):
|
||||
if move.location_dest_id.usage == "customer":
|
||||
qty += self.env['product.uom']._compute_qty_obj(move.product_uom, move.product_uom_qty, self.product_uom)
|
||||
qty += move.product_uom._compute_quantity(move.product_uom_qty, self.product_uom)
|
||||
elif move.location_dest_id.usage == "internal" and move.to_refund_so:
|
||||
qty -= self.env['product.uom']._compute_qty_obj(move.product_uom, move.product_uom_qty, self.product_uom)
|
||||
qty -= move.product_uom._compute_quantity(move.product_uom_qty, self.product_uom)
|
||||
return qty
|
||||
|
||||
@api.multi
|
||||
@@ -193,7 +193,7 @@ class SaleOrderLine(models.Model):
|
||||
default_uom = self.product_id.uom_id
|
||||
pack = self.product_packaging
|
||||
qty = self.product_uom_qty
|
||||
q = self.env['product.uom']._compute_qty_obj(default_uom, pack.qty, self.product_uom)
|
||||
q = default_uom._compute_quantity(pack.qty, self.product_uom)
|
||||
if qty and q and (qty % q):
|
||||
newqty = qty - (qty % q) + q
|
||||
return {
|
||||
|
||||
@@ -37,7 +37,7 @@ class procurement_order(osv.osv):
|
||||
product_uom = self.pool.get('product.uom')
|
||||
company_time_uom_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id
|
||||
if procurement.product_uom.id != company_time_uom_id.id and procurement.product_uom.category_id.id == company_time_uom_id.category_id.id:
|
||||
planned_hours = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, company_time_uom_id.id)
|
||||
planned_hours = product_uom._compute_quantity(cr, uid, [procurement.product_uom.id], procurement.product_qty, company_time_uom_id)
|
||||
else:
|
||||
planned_hours = procurement.product_qty
|
||||
return planned_hours
|
||||
|
||||
@@ -318,7 +318,7 @@ class InventoryLine(models.Model):
|
||||
return
|
||||
theoretical_qty = sum([x.qty for x in self._get_quants()])
|
||||
if theoretical_qty and self.product_uom_id and self.product_id.uom_id != self.product_uom_id:
|
||||
theoretical_qty = self.env["product.uom"]._compute_qty_obj(self.product_id.uom_id, theoretical_qty, self.product_uom_id)
|
||||
theoretical_qty = self.product_id.uom_id._compute_quantity(theoretical_qty, self.product_uom_id)
|
||||
self.theoretical_qty = theoretical_qty
|
||||
|
||||
@api.onchange('product_id', 'product_uom_id')
|
||||
|
||||
@@ -156,7 +156,7 @@ class StockMove(models.Model):
|
||||
@api.depends('product_id', 'product_uom', 'product_uom_qty')
|
||||
def _compute_product_qty(self):
|
||||
if self.product_uom:
|
||||
self.product_qty = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, self.product_id.uom_id)
|
||||
self.product_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id)
|
||||
|
||||
def _set_product_qty(self):
|
||||
""" The meaning of product_qty field changed lately and is now a functional field computing the quantity
|
||||
@@ -195,7 +195,6 @@ class StockMove(models.Model):
|
||||
@api.multi
|
||||
def _compute_string_qty_information(self):
|
||||
StockConfig = self.env['stock.config.settings']
|
||||
UOM = self.env['product.uom']
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
void_moves = self.filtered(lambda move: move.state in ('draft', 'done', 'cancel') or move.location_id.usage != 'internal')
|
||||
other_moves = self - void_moves
|
||||
@@ -203,7 +202,7 @@ class StockMove(models.Model):
|
||||
move.string_availability_info = '' # 'not applicable' or 'n/a' could work too
|
||||
for move in other_moves:
|
||||
total_available = min(move.product_qty, move.reserved_availability + move.availability)
|
||||
total_available = UOM._compute_qty_obj(move.product_id.uom_id, total_available, move.product_uom, round=False)
|
||||
total_available = move.product_id.uom_id._compute_quantity(total_available, move.product_uom, round=False)
|
||||
total_available = float_round(total_available, precision_digits=precision)
|
||||
info = str(total_available)
|
||||
# look in the settings if we need to display the UoM name or not
|
||||
@@ -213,7 +212,7 @@ class StockMove(models.Model):
|
||||
if move.reserved_availability:
|
||||
if move.reserved_availability != total_available:
|
||||
# some of the available quantity is assigned and some are available but not reserved
|
||||
reserved_available = UOM._compute_qty_obj(move.product_id.uom_id, move.reserved_availability, move.product_uom, round=False)
|
||||
reserved_available = move.product_id.uom_id._compute_quantity(move.reserved_availability, move.product_uom, round=False)
|
||||
reserved_available = float_round(reserved_available, precision_digits=precision)
|
||||
info += _(' (%s reserved)') % str(reserved_available)
|
||||
else:
|
||||
@@ -615,7 +614,7 @@ class StockMove(models.Model):
|
||||
lot_qty = {}
|
||||
rounding = ops.product_id.uom_id.rounding
|
||||
for pack_lot in ops.pack_lot_ids:
|
||||
lot_qty[pack_lot.lot_id.id] = Uom._compute_qty_obj(ops.product_uom_id, pack_lot.qty, ops.product_id.uom_id)
|
||||
lot_qty[pack_lot.lot_id.id] = ops.product_uom_id._compute_quantity(pack_lot.qty, ops.product_id.uom_id)
|
||||
for record in ops.linked_move_operation_ids:
|
||||
move_qty = record.qty
|
||||
move = record.move_id
|
||||
@@ -791,8 +790,7 @@ class StockMove(models.Model):
|
||||
entire_pack = not operation.product_id and True or False
|
||||
|
||||
# compute quantities for each lot + check quantities match
|
||||
lot_quantities = dict((pack_lot.lot_id.id, Uom._compute_qty_obj(
|
||||
operation.product_uom_id, pack_lot.qty, operation.product_id.uom_id)
|
||||
lot_quantities = dict((pack_lot.lot_id.id, operation.product_uom_id._compute_quantity(pack_lot.qty, operation.product_id.uom_id)
|
||||
) for pack_lot in operation.pack_lot_ids)
|
||||
if operation.pack_lot_ids and float_compare(sum(lot_quantities.values()), operation.product_qty, precision_rounding=operation.product_uom_id.rounding) != 0.0:
|
||||
raise UserError(_('You have a difference between the quantity on the operation and the quantities specified for the lots. '))
|
||||
@@ -918,7 +916,7 @@ class StockMove(models.Model):
|
||||
return self.id
|
||||
|
||||
# HALF-UP rounding as only rounding errors will be because of propagation of error from default UoM
|
||||
uom_qty = self.env['product.uom']._compute_qty_obj(self.product_id.uom_id, qty, self.product_uom, rounding_method='HALF-UP')
|
||||
uom_qty = self.product_id.uom_id._compute_quantity(qty, self.product_uom, rounding_method='HALF-UP')
|
||||
defaults = {
|
||||
'product_uom_qty': uom_qty,
|
||||
'procure_method': 'make_to_stock',
|
||||
|
||||
@@ -107,7 +107,7 @@ class PackOperation(models.Model):
|
||||
else:
|
||||
qty = self.product_qty
|
||||
if self.product_uom_id:
|
||||
qty = self.env['product.uom']._compute_qty_obj(self.product_uom_id, self.product_qty, self.product_id.uom_id)
|
||||
qty = self.product_uom_id._compute_quantity(self.product_qty, self.product_id.uom_id)
|
||||
for record in self.linked_move_operation_ids:
|
||||
qty -= record.qty
|
||||
self.remaining_qty = float_round(qty, precision_rounding=self.product_id.uom_id.rounding)
|
||||
|
||||
@@ -557,7 +557,7 @@ class Picking(models.Model):
|
||||
uom = product_to_uom[mapping.product.id]
|
||||
val_dict = {
|
||||
'picking_id': self.id,
|
||||
'product_qty': Uom._compute_qty_obj(mapping.product.uom_id, qty, uom),
|
||||
'product_qty': mapping.product.uom_id._compute_quantity(qty, uom),
|
||||
'product_id': mapping.product.id,
|
||||
'package_id': mapping.package.id,
|
||||
'owner_id': mapping.owner.id,
|
||||
@@ -686,7 +686,7 @@ class Picking(models.Model):
|
||||
for ops in operations:
|
||||
lot_qty = {}
|
||||
for packlot in ops.pack_lot_ids:
|
||||
lot_qty[packlot.lot_id.id] = Uom._compute_qty_obj(ops.product_uom_id, packlot.qty, ops.product_id.uom_id)
|
||||
lot_qty[packlot.lot_id.id] = ops.product_uom_id._compute_quantity(packlot.qty, ops.product_id.uom_id)
|
||||
# for each operation, create the links with the stock move by seeking on the matching reserved quants,
|
||||
# and deffer the operation if there is some ambiguity on the move to select
|
||||
if ops.package_id and not ops.product_id and (not done_qtys or ops.qty_done):
|
||||
@@ -704,7 +704,7 @@ class Picking(models.Model):
|
||||
elif ops.product_id.id:
|
||||
# Check moves with same product
|
||||
product_qty = ops.qty_done if done_qtys else ops.product_qty
|
||||
qty_to_assign = Uom._compute_qty_obj(ops.product_uom_id, product_qty, ops.product_id.uom_id)
|
||||
qty_to_assign = ops.product_uom_id._compute_quantity(product_qty, ops.product_id.uom_id)
|
||||
precision_rounding = ops.product_id.uom_id.rounding
|
||||
for move_dict in prod2move_ids.get(ops.product_id.id, []):
|
||||
move = move_dict['move']
|
||||
@@ -927,7 +927,7 @@ class Picking(models.Model):
|
||||
if op.product_uom_id.factor > product.uom_id.factor: # If the pack operation's is a smaller unit
|
||||
uom_id = op.product_uom_id.id
|
||||
# HALF-UP rounding as only rounding errors will be because of propagation of error from default UoM
|
||||
qty = Uom._compute_qty_obj(product.uom_id, remaining_qty, op.product_uom_id, rounding_method='HALF-UP')
|
||||
qty = product.uom_id._compute_quantity(remaining_qty, op.product_uom_id, rounding_method='HALF-UP')
|
||||
picking = op.picking_id
|
||||
ref = product.default_code
|
||||
name = '[' + ref + ']' + ' ' + product.name if ref else product.name
|
||||
|
||||
@@ -801,7 +801,7 @@ class Orderpoint(models.Model):
|
||||
for orderpoint_id, procurement_id, product_uom_id, procurement_qty, template_uom_id, move_qty in self._cr.fetchall():
|
||||
if procurement_id not in procurements_done: # count procurement once, if multiple move in this orderpoint/procurement combo
|
||||
procurements_done.add(procurement_id)
|
||||
res[orderpoint_id] += UoM._compute_qty(product_uom_id, procurement_qty, template_uom_id, round=False)
|
||||
res[orderpoint_id] += UoM.browse(product_uom_id)._compute_quantity(procurement_qty, UoM.browse(template_uom_id), round=False)
|
||||
if move_qty:
|
||||
res[orderpoint_id] -= move_qty
|
||||
return res
|
||||
|
||||
@@ -53,7 +53,7 @@ class ReturnPicking(models.TransientModel):
|
||||
]).filtered(
|
||||
lambda quant: not quant.reservation_id or quant.reservation_id.origin_returned_move_id != move)
|
||||
)
|
||||
quantity = self.env['product.uom']._compute_qty_obj(move.product_id.uom_id, quantity, move.product_uom)
|
||||
quantity = move.product_id.uom_id._compute_quantity(quantity, move.product_uom)
|
||||
product_return_moves.append((0, 0, {'product_id': move.product_id.id, 'quantity': quantity, 'move_id': move.id}))
|
||||
|
||||
if not product_return_moves:
|
||||
|
||||
Reference in New Issue
Block a user