[FIX] purchase-stock: Limit get_price_unit from invoice to 'purchase' purchase_method
# HOW TO REPRODUCE - Create Product P, storable, AVCO - Create Purchase Order for 100 units of P for $10 each > confirm - Receive 40 units of P, create backorder - Create Bill, change price to $12, confirm - Return 10 units of P - Receive 60 units of P => unit-cost in SVL is $12 instead of $10 OPW-3635451 closes odoo/odoo#149312 X-original-commit: 734149fbb3473f9a943c47d4ec13ab16afe2b35a Signed-off-by: William Henrotin (whe) <whe@odoo.com> Signed-off-by: David Fesquet (dafr) <dafr@odoo.com>
This commit is contained in:
@@ -47,7 +47,7 @@ class StockMove(models.Model):
|
||||
received_qty = line.qty_received
|
||||
if self.state == 'done':
|
||||
received_qty -= self.product_uom._compute_quantity(self.quantity, line.product_uom, rounding_method='HALF-UP')
|
||||
if float_compare(line.qty_invoiced, received_qty, precision_rounding=line.product_uom.rounding) > 0:
|
||||
if line.product_id.purchase_method == 'purchase' and float_compare(line.qty_invoiced, received_qty, precision_rounding=line.product_uom.rounding) > 0:
|
||||
move_layer = line.move_ids.sudo().stock_valuation_layer_ids
|
||||
invoiced_layer = line.sudo().invoice_lines.stock_valuation_layer_ids
|
||||
# value on valuation layer is in company's currency, while value on invoice line is in order's currency
|
||||
|
||||
@@ -2713,6 +2713,59 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
|
||||
{'date': one_day_ago, 'debit': 25, 'credit': 0, 'reconciled': True},
|
||||
])
|
||||
|
||||
def test_purchase_with_backorders_and_return_and_price_changes(self):
|
||||
"""
|
||||
When you have multiples receipts associated to a Purchase Order, with 1 bill for each receipt,
|
||||
then each bill has an impact on its own receipt only, hence if I modify the price on Bill01,
|
||||
it will not have an effect on Receipt02.
|
||||
However, if we create a return for a portion of a receipt,
|
||||
the invoiced_qty will be higher than the received_qty. This could be iterpreted has the bill
|
||||
being done before the receipt, which is not the case.
|
||||
In this test, we ensure that if the Control Policy is 'On received quantities' (procure_method = 'receive'),
|
||||
we keep using the purchase price for the svl unit_cost even when invoiced_qty > received_qty.
|
||||
"""
|
||||
self.product1.categ_id.property_cost_method = 'average'
|
||||
self.product1.categ_id.property_valuation = 'real_time'
|
||||
self.product1.purchase_method = 'receive' # ControlPolicy
|
||||
|
||||
po_form = Form(self.env['purchase.order'])
|
||||
po_form.partner_id = self.partner_id
|
||||
with po_form.order_line.new() as po_line:
|
||||
po_line.product_id = self.product1
|
||||
po_line.product_qty = 100
|
||||
po_line.price_unit = 10.0
|
||||
po = po_form.save()
|
||||
po.button_confirm()
|
||||
|
||||
def _validate_backorder(po, qty):
|
||||
picking = po.picking_ids.filtered(lambda p: p.state not in ['done', 'draft', 'cancel']).ensure_one()
|
||||
picking.move_ids.move_line_ids.quantity = qty
|
||||
picking.button_validate()
|
||||
# Validate picking with backorder
|
||||
res_dict = picking.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
return picking
|
||||
|
||||
receipt01 = _validate_backorder(po, 30)
|
||||
self.assertEqual(receipt01.move_ids.stock_valuation_layer_ids.ensure_one().value, 300.0)
|
||||
bill01 = self._bill(po, price=12)
|
||||
self.assertEqual(bill01.invoice_line_ids.stock_valuation_layer_ids.ensure_one().value, 60.0)
|
||||
|
||||
receipt02 = _validate_backorder(po, 30)
|
||||
# Even though Bill01 updated the price for Receipt01, the layers of Receipt02 are not impacted.
|
||||
self.assertEqual(receipt02.move_ids.stock_valuation_layer_ids.ensure_one().value, 300.0)
|
||||
bill02 = self._bill(po, price=13)
|
||||
self.assertEqual(bill02.invoice_line_ids.stock_valuation_layer_ids.ensure_one().value, 90.0)
|
||||
|
||||
# With the return, the invoiced qty > received qty,
|
||||
# this must NOT be interpreted as the invoice done before the picking (purchase_method = 'purchase')
|
||||
self._return(receipt02, qty=10)
|
||||
|
||||
receipt03 = _validate_backorder(po, 30)
|
||||
# Like Receipt02 layers, Receipt03 layers should not be impacted by the previous price changes.
|
||||
self.assertEqual(receipt03.move_ids.stock_valuation_layer_ids.ensure_one().value, 300.0)
|
||||
|
||||
def test_invoice_on_ordered_qty_with_backorder_and_different_currency_automated(self):
|
||||
"""Create a PO with currency different from the company currency. Set the
|
||||
product to be invoiced on ordered quantities. Receive partially the products
|
||||
|
||||
Reference in New Issue
Block a user