stock_landed_costs/tests/test_stock_landed_costs_rounding.py

286 lines
12 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.stock_landed_costs.tests.common import TestStockLandedCostsCommon
from odoo.tests import tagged, Form
@tagged('post_install', '-at_install')
class TestStockLandedCostsRounding(TestStockLandedCostsCommon):
def test_stock_landed_costs_rounding(self):
# In order to test the rounding in landed costs feature of stock, I create 2 landed cost
# Define undivisible units
product_uom_unit_round_1 = self.env.ref('uom.product_uom_unit')
product_uom_unit_round_1.write({
'name': 'Undivisible Units',
'rounding': 1.0,
})
# I create 2 products with different cost prices and configure them for real_time
# valuation and real price costing method
product_landed_cost_3 = self.env['product.product'].create({
'name': "LC product 3",
'uom_id': product_uom_unit_round_1.id,
})
product_landed_cost_3.product_tmpl_id.categ_id.property_cost_method = 'fifo'
product_landed_cost_3.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.company_data['default_account_expense']
product_landed_cost_3.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.company_data['default_account_revenue']
product_landed_cost_4 = self.env['product.product'].create({
'name': "LC product 4",
'uom_id': product_uom_unit_round_1.id,
})
product_landed_cost_4.product_tmpl_id.categ_id.property_cost_method = 'fifo'
product_landed_cost_4.product_tmpl_id.categ_id.property_valuation = 'real_time'
product_landed_cost_4.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.company_data['default_account_expense']
product_landed_cost_4.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.company_data['default_account_revenue']
picking_default_vals = self.env['stock.picking'].default_get(list(self.env['stock.picking'].fields_get()))
# I create 2 pickings moving those products
vals = dict(picking_default_vals, **{
'name': 'LC_pick_3',
'picking_type_id': self.warehouse.in_type_id.id,
'move_ids': [(0, 0, {
'product_id': product_landed_cost_3.id,
'product_uom_qty': 13,
'product_uom': product_uom_unit_round_1.id,
'location_id': self.ref('stock.stock_location_customers'),
'location_dest_id': self.warehouse.lot_stock_id.id,
})],
})
picking_landed_cost_3 = self.env['stock.picking'].new(vals)
picking_landed_cost_3._onchange_picking_type()
picking_landed_cost_3.move_ids._onchange_product_id()
picking_landed_cost_3.move_ids.name = 'move 3'
vals = picking_landed_cost_3._convert_to_write(picking_landed_cost_3._cache)
picking_landed_cost_3 = self.env['stock.picking'].create(vals)
vals = dict(picking_default_vals, **{
'name': 'LC_pick_4',
'picking_type_id': self.warehouse.in_type_id.id,
'move_ids': [(0, 0, {
'product_id': product_landed_cost_4.id,
'product_uom_qty': 1,
'product_uom': self.ref('uom.product_uom_dozen'),
'location_id': self.ref('stock.stock_location_customers'),
'location_dest_id': self.warehouse.lot_stock_id.id,
'price_unit': 17.00 / 12.00,
})],
})
picking_landed_cost_4 = self.env['stock.picking'].new(vals)
picking_landed_cost_4._onchange_picking_type()
picking_landed_cost_4.move_ids._onchange_product_id()
picking_landed_cost_4.move_ids.name = 'move 4'
vals = picking_landed_cost_4._convert_to_write(picking_landed_cost_4._cache)
picking_landed_cost_4 = self.env['stock.picking'].create(vals)
# We perform all the tests for LC_pick_3
# I receive picking LC_pick_3, and check how many quants are created
picking_landed_cost_3.move_ids.price_unit = 1.0
picking_landed_cost_3.action_confirm()
picking_landed_cost_3.action_assign()
picking_landed_cost_3._action_done()
virtual_interior_design = self.env['product.product'].create({'name': 'Virtual Interior Design'})
# I create a landed cost for picking 3
default_vals = self.env['stock.landed.cost'].default_get(list(self.env['stock.landed.cost'].fields_get()))
default_vals.update({
'picking_ids': [picking_landed_cost_3.id],
'account_journal_id': self.expenses_journal,
'cost_lines': [(0, 0, {'product_id': virtual_interior_design.id})],
'valuation_adjustment_lines': [],
})
stock_landed_cost_2 = self.env['stock.landed.cost'].new(default_vals)
stock_landed_cost_2.cost_lines.onchange_product_id()
stock_landed_cost_2.cost_lines.name = 'equal split'
stock_landed_cost_2.cost_lines.split_method = 'equal'
stock_landed_cost_2.cost_lines.price_unit = 15
vals = stock_landed_cost_2._convert_to_write(stock_landed_cost_2._cache)
stock_landed_cost_2 = self.env['stock.landed.cost'].create(vals)
# I compute the landed cost using Compute button
stock_landed_cost_2.compute_landed_cost()
# I check the valuation adjustment lines
for valuation in stock_landed_cost_2.valuation_adjustment_lines:
self.assertEqual(valuation.additional_landed_cost, 15)
# I confirm the landed cost
stock_landed_cost_2.button_validate()
# I check that the landed cost is now "Closed" and that it has an accounting entry
self.assertEqual(stock_landed_cost_2.state, 'done')
self.assertTrue(stock_landed_cost_2.account_move_id)
# We perform all the tests for LC_pick_4
# I receive picking LC_pick_4, and check how many quants are created
picking_landed_cost_4.move_ids.price_unit = 17.0/12.0
picking_landed_cost_4.action_confirm()
picking_landed_cost_4.action_assign()
picking_landed_cost_4._action_done()
# I create a landed cost for picking 4
default_vals = self.env['stock.landed.cost'].default_get(list(self.env['stock.landed.cost'].fields_get()))
default_vals.update({
'picking_ids': [picking_landed_cost_4.id],
'account_journal_id': self.expenses_journal,
'cost_lines': [(0, 0, {'product_id': virtual_interior_design.id})],
'valuation_adjustment_lines': [],
})
stock_landed_cost_3 = self.env['stock.landed.cost'].new(default_vals)
stock_landed_cost_3.cost_lines.onchange_product_id()
stock_landed_cost_3.cost_lines.name = 'equal split'
stock_landed_cost_3.cost_lines.split_method = 'equal'
stock_landed_cost_3.cost_lines.price_unit = 11
vals = stock_landed_cost_3._convert_to_write(stock_landed_cost_3._cache)
stock_landed_cost_3 = self.env['stock.landed.cost'].create(vals)
# I compute the landed cost using Compute button
stock_landed_cost_3.compute_landed_cost()
# I check the valuation adjustment lines
for valuation in stock_landed_cost_3.valuation_adjustment_lines:
self.assertEqual(valuation.additional_landed_cost, 11)
# I confirm the landed cost
stock_landed_cost_3.button_validate()
# I check that the landed cost is now "Closed" and that it has an accounting entry
self.assertEqual(stock_landed_cost_3.state, 'done')
self.assertTrue(stock_landed_cost_3.account_move_id)
def test_stock_landed_costs_rounding_02(self):
""" The landed costs should be correctly computed, even when the decimal accuracy
of the deciaml price is increased. """
self.env.ref("product.decimal_price").digits = 4
fifo_pc = self.env['product.category'].create({
'name': 'Fifo Category',
'parent_id': self.env.ref("product.product_category_all").id,
'property_valuation': 'real_time',
'property_cost_method': 'fifo',
})
products = self.Product.create([{
'name': 'Super Product %s' % price,
'categ_id': fifo_pc.id,
'type': 'product',
'standard_price': price,
} for price in [0.91, 0.93, 75.17, 20.54]])
landed_product = self.Product.create({
'name': 'Landed Costs',
'type': 'service',
'landed_cost_ok': True,
'split_method_landed_cost': 'by_quantity',
'standard_price': 1000.0,
})
po = self.env['purchase.order'].create({
'partner_id': self.partner_a.id,
'order_line': [(0, 0, {
'product_id': product.id,
'product_qty': qty,
'price_unit': product.standard_price,
}) for product, qty in zip(products, [6, 6, 3, 6])]
})
po.button_confirm()
po.picking_ids.button_validate()
lc_form = Form(self.LandedCost)
lc_form.picking_ids.add(po.picking_ids)
with lc_form.cost_lines.new() as line:
line.product_id = landed_product
lc = lc_form.save()
lc.compute_landed_cost()
self.assertEqual(sum(lc.valuation_adjustment_lines.mapped('additional_landed_cost')), 1000.0)
def test_stock_landed_costs_rounding_03(self):
"""
Storable AVCO product
Receive:
5 @ 5
5 @ 8
5 @ 7
20 @ 7.33
Add landed cost of $5 to each receipt (except the first one)
Deliver:
23
2
10
At the end, the SVL value should be zero
"""
self.product_a.type = 'product'
self.product_a.categ_id.property_cost_method = 'average'
stock_location = self.warehouse.lot_stock_id
supplier_location_id = self.ref('stock.stock_location_suppliers')
customer_location_id = self.ref('stock.stock_location_customers')
receipts = self.env['stock.picking'].create([{
'picking_type_id': self.warehouse.in_type_id.id,
'location_id': supplier_location_id,
'location_dest_id': stock_location.id,
'move_ids': [(0, 0, {
'name': self.product_a.name,
'product_id': self.product_a.id,
'price_unit': price,
'product_uom': self.product_a.uom_id.id,
'product_uom_qty': qty,
'location_id': supplier_location_id,
'location_dest_id': stock_location.id,
})]
} for qty, price in [
(5, 5.0),
(5, 8.0),
(5, 7.0),
(20, 7.33),
]])
receipts.action_confirm()
for m in receipts.move_ids:
m.quantity = m.product_uom_qty
receipts.button_validate()
landed_costs = self.env['stock.landed.cost'].create([{
'picking_ids': [(6, 0, picking.ids)],
'account_journal_id': self.expenses_journal.id,
'cost_lines': [(0, 0, {
'name': 'equal split',
'split_method': 'equal',
'price_unit': 5.0,
'product_id': self.landed_cost.id
})],
} for picking in receipts[1:]])
landed_costs.compute_landed_cost()
landed_costs.button_validate()
self.assertEqual(self.product_a.standard_price, 7.47)
deliveries = self.env['stock.picking'].create([{
'picking_type_id': self.warehouse.out_type_id.id,
'location_id': stock_location.id,
'location_dest_id': customer_location_id,
'move_ids': [(0, 0, {
'name': self.product_a.name,
'product_id': self.product_a.id,
'product_uom': self.product_a.uom_id.id,
'product_uom_qty': qty,
'location_id': stock_location.id,
'location_dest_id': customer_location_id,
})]
} for qty in [23, 2, 10]])
deliveries.action_confirm()
for m in deliveries.move_ids:
m.quantity = m.product_uom_qty
deliveries.button_validate()
self.assertEqual(self.product_a.value_svl, 0)