[MERGE] stock_account: remove property_cost_method and property_valuation

The fields property_cost_method ad property_valuation are never shown on the products but they sometimes are set. This creates confusion and some difficulties in the migration (the cost method/valuation on the products are different than the one set on the categories).

We remove them and only use the one on the categories.

Task: 1866333

closes odoo/odoo#26008
This commit is contained in:
Robot Odoo
2018-12-03 14:05:52 +01:00
committed by GitHub
15 changed files with 123 additions and 199 deletions
@@ -24,13 +24,13 @@ class TestAveragePrice(TestPurchase):
'standard_price': 60.0,
'uom_id': self.env.ref('uom.product_uom_kgm').id,
'uom_po_id': self.env.ref('uom.product_uom_kgm').id,
'cost_method': 'average',
'valuation': 'real_time',
'property_stock_account_input': self.ref('purchase.o_expense'),
'property_stock_account_output': self.ref('purchase.o_income'),
'supplier_taxes_id': [],
'description': 'FIFO Ice Cream',
})
product_cable_management_box.categ_id.property_cost_method = 'average'
product_cable_management_box.categ_id.property_valuation = 'real_time'
product_cable_management_box.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense')
product_cable_management_box.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income')
# I create a draft Purchase Order for first incoming shipment for 10 pieces at 60€
purchase_order_1 = self.env['purchase.order'].create({
@@ -23,13 +23,13 @@ class TestFifoPrice(TestPurchase):
'standard_price': 70.0,
'uom_id': self.env.ref('uom.product_uom_kgm').id,
'uom_po_id': self.env.ref('uom.product_uom_kgm').id,
'cost_method': 'fifo',
'valuation': 'real_time',
'property_stock_account_input': self.ref('purchase.o_expense'),
'property_stock_account_output': self.ref('purchase.o_income'),
'supplier_taxes_id': '[]',
'description': 'FIFO Ice Cream',
})
product_cable_management_box.categ_id.property_cost_method = 'fifo'
product_cable_management_box.categ_id.property_valuation = 'real_time'
product_cable_management_box.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense')
product_cable_management_box.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income')
# I create a draft Purchase Order for first in move for 10 kg at 50 euro
purchase_order_1 = self.env['purchase.order'].create({
@@ -217,13 +217,13 @@ class TestFifoPrice(TestPurchase):
'standard_price': 70.0,
'uom_id': self.env.ref('uom.product_uom_kgm').id,
'uom_po_id': self.env.ref('uom.product_uom_kgm').id,
'cost_method': 'fifo',
'valuation': 'real_time',
'property_stock_account_input': self.ref('purchase.o_expense'),
'property_stock_account_output': self.ref('purchase.o_income'),
'supplier_taxes_id': '[]',
'description': 'FIFO Ice Cream',
})
product_fifo_negative.categ_id.property_cost_method = 'fifo'
product_fifo_negative.categ_id.property_valuation = 'real_time'
product_fifo_negative.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense')
product_fifo_negative.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income')
# Create outpicking.create delivery order of 100 kg.
outgoing_shipment_neg = self.env['stock.picking'].create({
@@ -22,12 +22,12 @@ class TestFifoReturns(TestPurchase):
'standard_price': 0.0,
'uom_id': self.env.ref('uom.product_uom_kgm').id,
'uom_po_id': self.env.ref('uom.product_uom_kgm').id,
'cost_method': 'fifo',
'valuation': 'real_time',
'property_stock_account_input': self.ref('purchase.o_expense'),
'property_stock_account_output': self.ref('purchase.o_income'),
'description': 'FIFO Ice Cream',
})
product_fiforet_icecream.categ_id.property_cost_method = 'fifo'
product_fiforet_icecream.categ_id.property_valuation = 'real_time'
product_fiforet_icecream.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense')
product_fiforet_icecream.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income')
# I create a draft Purchase Order for first in move for 10 kg at 50 euro
purchase_order_1 = self.env['purchase.order'].create({
@@ -53,7 +53,7 @@ class TestStockValuation(TransactionCase):
purchase order before validating the receipt, the value of the received goods should be set
according to the last unit cost.
"""
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
po1 = self.env['purchase.order'].create({
'partner_id': self.partner_id.id,
'order_line': [
@@ -96,7 +96,7 @@ class TestStockValuation(TransactionCase):
purchase order and the standard price of the product before validating the receipt, the
value of the received goods should be set according to the last standard price.
"""
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
# set a standard price
self.product1.product_tmpl_id.standard_price = 10
@@ -149,7 +149,7 @@ class TestStockValuation(TransactionCase):
eur_currency = self.env.ref('base.EUR')
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
# default currency is USD, create a purchase order in EUR
po1 = self.env['purchase.order'].create({
@@ -212,7 +212,7 @@ class TestStockValuation(TransactionCase):
""" Check that the extra move when over processing a receipt is correctly merged back in
the original move.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
po1 = self.env['purchase.order'].create({
'partner_id': self.partner_id.id,
'order_line': [
@@ -246,7 +246,7 @@ class TestStockValuation(TransactionCase):
""" Check that the backordered move when under processing a receipt correctly keep the
price unit of the original move.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
po1 = self.env['purchase.order'].create({
'partner_id': self.partner_id.id,
'order_line': [
@@ -321,8 +321,8 @@ class TestStockValuationWithCOA(AccountingTestCase):
def test_fifo_anglosaxon_return(self):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'delivery'
price_diff_account = self.env['account.account'].create({
'name': 'price diff account',
@@ -421,8 +421,8 @@ class TestStockValuationWithCOA(AccountingTestCase):
def test_anglosaxon_valuation(self):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'delivery'
price_diff_account = self.env['account.account'].create({
'name': 'price diff account',
@@ -1,18 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record forcecreate="True" id="property_stock_account_output_prd" model="ir.property">
<field name="name">property_stock_account_output</field>
<field name="fields_id" search="[('model','=','product.template'),('name','=','property_stock_account_output')]"/>
<field eval="False" name="value"/>
<field name="company_id" ref="base.main_company"/>
</record>
<record forcecreate="True" id="property_stock_account_input_prd" model="ir.property">
<field name="name">property_stock_account_input</field>
<field name="fields_id" search="[('model','=','product.template'),('name','=','property_stock_account_input')]"/>
<field eval="False" name="value"/>
<field name="company_id" ref="base.main_company"/>
</record>
<record forcecreate="True" id="property_stock_account_output_categ_id" model="ir.property">
<field name="name">property_stock_account_output_categ_id</field>
<field name="fields_id" search="[('model','=','product.category'),('name','=','property_stock_account_output_categ_id')]"/>
@@ -1,18 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record forcecreate="True" id="default_cost_method" model="ir.property">
<field name="name">Cost Method Property</field>
<field name="fields_id" ref="field_product_template__property_cost_method"/>
<field name="value" eval="False" />
<field name="type">selection</field>
</record>
<record forcecreate="True" id="default_valuation" model="ir.property">
<field name="name">Valuation Property</field>
<field name="fields_id" ref="field_product_template__property_valuation"/>
<field name="value" eval="False" />
<field name="type">selection</field>
</record>
<record forcecreate="True" id="default_category_cost_method" model="ir.property">
<field name="name">Cost Method Property</field>
+23 -57
View File
@@ -12,62 +12,11 @@ class ProductTemplate(models.Model):
_name = 'product.template'
_inherit = 'product.template'
property_valuation = fields.Selection([
('manual_periodic', 'Periodic (manual)'),
('real_time', 'Perpetual (automated)')], string='Inventory Valuation',
company_dependent=True, copy=True, default='manual_periodic',
help="""Manual: The accounting entries to value the inventory are not posted automatically.
Automated: An accounting entry is automatically created to value the inventory when a product enters or leaves the company.""")
valuation = fields.Char(compute='_compute_valuation_type', inverse='_set_valuation_type')
property_cost_method = fields.Selection([
('standard', 'Standard Price'),
('fifo', 'First In First Out (FIFO)'),
('average', 'Average Cost (AVCO)')], string='Costing Method',
company_dependent=True, copy=True,
help="""Standard Price: The products are valued at their standard cost defined on the product.
Average Cost (AVCO): The products are valued at weighted average cost.
First In First Out (FIFO): The products are valued supposing those that enter the company first will also leave it first.""")
cost_method = fields.Char(compute='_compute_cost_method', inverse='_set_cost_method')
property_stock_account_input = fields.Many2one(
'account.account', 'Stock Input Account',
company_dependent=True, domain=[('deprecated', '=', False)],
help="When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless "
"there is a specific valuation account set on the source location. When not set on the product, the one from the product category is used.")
property_stock_account_output = fields.Many2one(
'account.account', 'Stock Output Account',
company_dependent=True, domain=[('deprecated', '=', False)],
help="When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless "
"there is a specific valuation account set on the destination location. When not set on the product, the one from the product category is used.")
@api.one
@api.depends('property_valuation', 'categ_id.property_valuation')
def _compute_valuation_type(self):
self.valuation = self.property_valuation or self.categ_id.property_valuation
@api.one
def _set_valuation_type(self):
return self.write({'property_valuation': self.valuation})
@api.one
@api.depends('property_cost_method', 'categ_id.property_cost_method')
def _compute_cost_method(self):
self.cost_method = self.property_cost_method or self.categ_id.property_cost_method
cost_method = fields.Selection(related="categ_id.property_cost_method", readonly=True)
valuation = fields.Selection(related="categ_id.property_valuation", readonly=True)
def _is_cost_method_standard(self):
return self.property_cost_method == 'standard'
@api.one
def _set_cost_method(self):
# When going from FIFO to AVCO or to standard, we update the standard price with the
# average value in stock.
if self.property_cost_method == 'fifo' and self.cost_method in ['average', 'standard']:
# Cannot use the `stock_value` computed field as it's already invalidated when
# entering this method.
valuation = sum([variant._sum_remaining_values()[0] for variant in self.product_variant_ids])
qty_available = self.with_context(company_owned=True).qty_available
if qty_available:
self.standard_price = valuation / qty_available
return self.write({'property_cost_method': self.cost_method})
return self.categ_id.property_cost_method == 'standard'
@api.multi
def _get_product_accounts(self):
@@ -77,8 +26,8 @@ class ProductTemplate(models.Model):
accounts = super(ProductTemplate, self)._get_product_accounts()
res = self._get_asset_accounts()
accounts.update({
'stock_input': res['stock_input'] or self.property_stock_account_input or self.categ_id.property_stock_account_input_categ_id,
'stock_output': res['stock_output'] or self.property_stock_account_output or self.categ_id.property_stock_account_output_categ_id,
'stock_input': res['stock_input'] or self.categ_id.property_stock_account_input_categ_id,
'stock_output': res['stock_output'] or self.categ_id.property_stock_account_output_categ_id,
'stock_valuation': self.categ_id.property_stock_valuation_account_id or False,
})
return accounts
@@ -177,7 +126,7 @@ class ProductProduct(models.Model):
return sum(moves.mapped('remaining_value')), moves
@api.multi
@api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.property_valuation', 'product_tmpl_id.categ_id.property_valuation')
@api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.categ_id.property_valuation')
def _compute_stock_value(self):
StockMove = self.env['stock.move']
to_date = self.env.context.get('to_date')
@@ -402,6 +351,14 @@ class ProductCategory(models.Model):
input_and_output_accounts = category.property_stock_account_input_categ_id | category.property_stock_account_output_categ_id
if valuation_account and valuation_account in input_and_output_accounts:
raise ValidationError(_('The Stock Input and/or Output accounts cannot be the same than the Stock Valuation account.'))
@api.multi
def write(self, vals):
# When going from FIFO to AVCO or to standard, we update the standard price with the
# average value in stock.
cost_method = vals.get('property_cost_method')
if cost_method and cost_method in ['average', 'standard']:
self._update_standard_price()
return super(ProductCategory, self).write(vals)
@api.onchange('property_cost_method')
def onchange_property_valuation(self):
@@ -414,3 +371,12 @@ class ProductCategory(models.Model):
'message': _("Changing your cost method is an important change that will impact your inventory valuation. Are you sure you want to make that change?"),
}
}
def _update_standard_price(self):
updated_categories = self.filtered(lambda x: x.property_cost_method == 'fifo')
templates = self.env['product.template'].search([('categ_id', 'in', updated_categories.ids)])
for t in templates:
valuation = sum([variant._sum_remaining_values()[0] for variant in t.product_variant_ids])
qty_available = t.with_context(company_owned=True).qty_available
if qty_available:
t.standard_price = valuation / qty_available
-2
View File
@@ -476,8 +476,6 @@ class StockMove(models.Model):
def _run_fifo_vacuum(self):
# Call `_fifo_vacuum` on concerned moves
fifo_valued_products = self.env['product.product']
fifo_valued_products |= self.env['product.template'].search([('property_cost_method', '=', 'fifo')]).mapped(
'product_variant_ids')
fifo_valued_categories = self.env['product.category'].search([('property_cost_method', '=', 'fifo')])
fifo_valued_products |= self.env['product.product'].search([('categ_id', 'child_of', fifo_valued_categories.ids)])
moves_to_vacuum = self.env['stock.move']
@@ -29,8 +29,8 @@ class TestStockValuation(TransactionCase):
'categ_id': self.env.ref('product.product_category_all').id,
})
self.product1.product_tmpl_id.valuation = 'real_time'
self.product2.product_tmpl_id.valuation = 'real_time'
self.product1.categ_id.property_valuation = 'real_time'
self.product2.categ_id.property_valuation = 'real_time'
Account = self.env['account.account']
self.stock_input_account = Account.create({
'name': 'Stock Input',
@@ -113,7 +113,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(price_change_aml.product_id, self.product1)
def test_fifo_perpetual_1(self):
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# receive 10 units @ 10.00 per unit
@@ -779,7 +779,7 @@ class TestStockValuation(TransactionCase):
def test_fifo_perpetual_2(self):
# http://accountingexplained.com/financial/inventories/fifo-method
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# Beginning Inventory: 68 units @ 15.00 per unit
move1 = self.env['stock.move'].create({
@@ -1223,7 +1223,7 @@ class TestStockValuation(TransactionCase):
""" Send products that you do not have. Value the first outgoing move to the standard
price, receive in multiple times the delivered quantity and run _fifo_vacuum to compensate.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# We expect the user to set manually set a standard price to its products if its first
# transfer is sending products that he doesn't have.
@@ -1416,7 +1416,7 @@ class TestStockValuation(TransactionCase):
price, running the vacuum should not do anything. Receive 2 units at the price the two
extra units were sent, check that no accounting entries are created.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# Receive 10@10
@@ -1584,7 +1584,7 @@ class TestStockValuation(TransactionCase):
""" Receives 10 units, send 10 units, then send more: the extra quantity should be valued
at the last fifo price, running the vacuum should not do anything.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# Receive 10@10
@@ -1750,7 +1750,7 @@ class TestStockValuation(TransactionCase):
IN03 2@30 product2
vacuum
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# Receive 10@10
@@ -1791,7 +1791,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# Add a stock move, receive 10@20 of another product
# ---------------------------------------------------------------------
self.product2.product_tmpl_id.cost_method = 'fifo'
self.product2.categ_id.property_cost_method = 'fifo'
self.product2.standard_price = 20
move2 = self.env['stock.move'].create({
'picking_id': receipt.id,
@@ -1974,7 +1974,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move4.value, -60) # after correction, the move is valued -(2*30)
def test_fifo_add_moveline_in_done_move_1(self):
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# Receive 10@10
@@ -2037,7 +2037,7 @@ class TestStockValuation(TransactionCase):
def test_fifo_edit_done_move1(self):
""" Increase OUT done move while quantities are available.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# Receive 10@10
@@ -2216,7 +2216,7 @@ class TestStockValuation(TransactionCase):
def test_fifo_edit_done_move2(self):
""" Decrease, then increase OUT done move while quantities are available.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# ---------------------------------------------------------------------
# Receive 10@10
@@ -2305,7 +2305,7 @@ class TestStockValuation(TransactionCase):
def test_average_perpetual_1(self):
# http://accountingexplained.com/financial/inventories/avco-method
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
# Beginning Inventory: 60 units @ 15.00 per unit
move1 = self.env['stock.move'].create({
@@ -2410,7 +2410,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move6.value, 0)
def test_average_perpetual_2(self):
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
move1 = self.env['stock.move'].create({
'name': 'Receive 10 units at 10',
@@ -2471,7 +2471,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(self.product1.stock_value, 87.5)
def test_average_perpetual_3(self):
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
move1 = self.env['stock.move'].create({
'name': 'Receive 10 units at 10',
@@ -2530,7 +2530,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(self.product1.stock_value, -187.5)
def test_average_perpetual_4(self):
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
move1 = self.env['stock.move'].create({
'name': 'Receive 1 unit at 10',
@@ -2566,7 +2566,7 @@ class TestStockValuation(TransactionCase):
def test_average_perpetual_5(self):
''' Set owner on incoming move => no valuation '''
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
move1 = self.env['stock.move'].create({
'name': 'Receive 1 unit at 10',
@@ -2590,7 +2590,7 @@ class TestStockValuation(TransactionCase):
def test_average_negative_1(self):
""" Test edit in the past. Receive 10, send 20, edit the second move to only send 10.
"""
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
move1 = self.env['stock.move'].create({
'name': 'Receive 10 units at 10',
@@ -2644,7 +2644,7 @@ class TestStockValuation(TransactionCase):
def test_average_negative_2(self):
""" Send goods that you don't have in stock and never received any unit.
"""
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
# set a standard price
self.product1.standard_price = 99
@@ -2667,7 +2667,7 @@ class TestStockValuation(TransactionCase):
def test_average_negative_3(self):
""" Send goods that you don't have in stock but received and send some units before.
"""
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method= 'average'
# set a standard price
self.product1.standard_price = 99
@@ -2722,7 +2722,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move3.value, -100.0) # as no move out were done for this product, fallback on latest cost
def test_average_negative_4(self):
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
# set a standard price
self.product1.standard_price = 99
@@ -2745,7 +2745,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move1.value, 100.0)
def test_average_negative_5(self):
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
# in 10 @ 10
move1 = self.env['stock.move'].create({
@@ -2871,8 +2871,8 @@ class TestStockValuation(TransactionCase):
def test_average_manual_1(self):
''' Set owner on incoming move => no valuation '''
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.product_tmpl_id.valuation = 'manual_periodic'
self.product1.categ_id.property_cost_method = 'average'
self.product1.categ_id.property_valuation = 'manual_periodic'
move1 = self.env['stock.move'].create({
'name': 'Receive 1 unit at 10',
@@ -2895,7 +2895,7 @@ class TestStockValuation(TransactionCase):
def test_standard_perpetual_1(self):
''' Set owner on incoming move => no valuation '''
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.categ_id.property_cost_method = 'standard'
move1 = self.env['stock.move'].create({
'name': 'Receive 1 unit at 10',
@@ -2918,8 +2918,8 @@ class TestStockValuation(TransactionCase):
def test_standard_manual_1(self):
''' Set owner on incoming move => no valuation '''
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.valuation = 'manual_periodic'
self.product1.categ_id.property_cost_method = 'standard'
self.product1.categ_id.property_valuation = 'manual_periodic'
move1 = self.env['stock.move'].create({
'name': 'Receive 1 unit at 10',
@@ -2946,7 +2946,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# Use FIFO, make some operations
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# receive 10@10
move1 = self.env['stock.move'].create({
@@ -2999,7 +2999,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# Change the production valuation to AVCO
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.cost_method = 'average'
self.product1.categ_id.property_cost_method = 'average'
# valuation should stay to ~240
self.assertAlmostEqual(self.product1.stock_value, 240, delta=0.03)
@@ -3016,7 +3016,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# Use FIFO, make some operations
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
# receive 10@10
move1 = self.env['stock.move'].create({
@@ -3069,7 +3069,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# Change the production valuation to AVCO
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.categ_id.property_cost_method = 'standard'
# valuation should stay to ~240
self.assertAlmostEqual(self.product1.stock_value, 240, delta=0.03)
@@ -3088,7 +3088,7 @@ class TestStockValuation(TransactionCase):
quants to a customer, only the one in the internal location
should be valued.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
view_location = self.env['stock.location'].create({'name': 'view', 'usage': 'view'})
subloc1 = self.env['stock.location'].create({
@@ -3258,7 +3258,7 @@ class TestStockValuation(TransactionCase):
move2._action_done()
def test_at_date_standard_1(self):
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.categ_id.property_cost_method = 'standard'
now = Datetime.now()
date1 = now - timedelta(days=8)
@@ -3452,7 +3452,7 @@ class TestStockValuation(TransactionCase):
date wizard are consistent. Afterwards, edit the done quantity of some operations. The
valuation at date results should take these changes into account.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
now = Datetime.now()
date1 = now - timedelta(days=8)
@@ -3579,7 +3579,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# ending: manual valuation
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.valuation = 'manual_periodic'
self.product1.categ_id.property_valuation = 'manual_periodic'
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 20)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 200)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 30)
@@ -3598,7 +3598,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# ending: perpetual valuation
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.categ_id.property_valuation = 'real_time'
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 10)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 100)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 20)
@@ -3615,7 +3615,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(self.product1.stock_value, 1375)
def test_at_date_fifo_2(self):
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.categ_id.property_cost_method = 'fifo'
now = Datetime.now()
date1 = now - timedelta(days=8)
@@ -3740,7 +3740,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# ending: manual valuation
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.valuation = 'manual_periodic'
self.product1.categ_id.property_valuation = 'manual_periodic'
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 10)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 100)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 20)
@@ -3759,7 +3759,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# ending: perpetual valuation
# ---------------------------------------------------------------------
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.categ_id.property_valuation = 'real_time'
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 10)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 100)
self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 20)
@@ -35,7 +35,6 @@
<field name="list_price" position="after">
<field name="valuation" invisible="1" readonly="1"/>
<field name="cost_method" invisible="1" readonly="1"/>
<field name="property_cost_method" invisible="1"/>
</field>
<field name="standard_price" position="replace">
<field name="standard_price"
@@ -49,15 +48,6 @@
class="oe_link oe_read_only"/>
</div>
</field>
<group name="accounting" position="inside">
<group name="property_inventory_valuation" string="Stock Valuation" attrs="{'invisible': ['|', ('type','=','service'), ('valuation', '!=', 'real_time')]}" groups="account.group_account_user">
<field name="property_valuation" invisible="1"/>
<field name="property_stock_account_input"
domain="[('deprecated', '=', False)]"/>
<field name="property_stock_account_output"
domain="[('deprecated', '=', False)]"/>
</group>
</group>
</data>
</field>
</record>
@@ -40,8 +40,8 @@ class TestLifoPrice(common.TransactionCase):
# category (or hand-assign the property_* version which seems...)
# product_form.valuation = 'real_time'
# product_form.cost_method = 'fifo'
product_form.property_stock_account_input = self.env.ref('stock_dropshipping.o_expense')
product_form.property_stock_account_output = self.env.ref('stock_dropshipping.o_income')
product_form.categ_id.property_stock_account_input_categ_id = self.env.ref('stock_dropshipping.o_expense')
product_form.categ_id.property_stock_account_output_categ_id = self.env.ref('stock_dropshipping.o_income')
product_lifo_icecream = product_form.save()
# I create a draft Purchase Order for first in move for 10 pieces at 60 euro
@@ -108,9 +108,9 @@ class TestStockValuation(AccountingTestCase):
# -------------------------------------------------------------------------
def test_dropship_standard_perpetual_continental_ordered(self):
self.env.user.company_id.anglo_saxon_accounting = False
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'order'
all_amls = self._dropship_product1()
@@ -126,9 +126,9 @@ class TestStockValuation(AccountingTestCase):
def test_dropship_standard_perpetual_continental_delivered(self):
self.env.user.company_id.anglo_saxon_accounting = False
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'delivery'
all_amls = self._dropship_product1()
@@ -144,9 +144,9 @@ class TestStockValuation(AccountingTestCase):
def test_dropship_fifo_perpetual_continental_ordered(self):
self.env.user.company_id.anglo_saxon_accounting = False
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.proprty_cost_method = 'fifo'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'order'
all_amls = self._dropship_product1()
@@ -163,9 +163,9 @@ class TestStockValuation(AccountingTestCase):
def test_dropship_fifo_perpetual_continental_delivered(self):
self.env.user.company_id.anglo_saxon_accounting = False
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'delivery'
all_amls = self._dropship_product1()
@@ -184,9 +184,9 @@ class TestStockValuation(AccountingTestCase):
# -------------------------------------------------------------------------
def test_dropship_standard_perpetual_anglosaxon_ordered(self):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'order'
all_amls = self._dropship_product1()
@@ -207,9 +207,9 @@ class TestStockValuation(AccountingTestCase):
def test_dropship_standard_perpetual_anglosaxon_delivered(self):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'delivery'
all_amls = self._dropship_product1()
@@ -230,9 +230,9 @@ class TestStockValuation(AccountingTestCase):
def test_dropship_fifo_perpetual_anglosaxon_ordered(self):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'order'
all_amls = self._dropship_product1()
@@ -250,9 +250,9 @@ class TestStockValuation(AccountingTestCase):
def test_dropship_fifo_perpetual_anglosaxon_delivered(self):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'delivery'
all_amls = self._dropship_product1()
@@ -272,7 +272,7 @@ class TestStockValuation(AccountingTestCase):
self.env.user.company_id.anglo_saxon_accounting = True
self.product1.product_tmpl_id.cost_method = 'standard'
self.product1.product_tmpl_id.standard_price = 10
self.product1.product_tmpl_id.valuation = 'real_time'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'order'
all_amls = self._dropship_product1()
+4 -7
View File
@@ -47,29 +47,26 @@ class TestStockLandedCostsCommon(AccountingTestCase):
self.product_refrigerator = self.Product.create({
'name': 'Refrigerator',
'type': 'product',
'cost_method': 'fifo',
'valuation': 'real_time',
'standard_price': 1.0,
'weight': 10,
'volume': 1,
'categ_id': self.categ_all.id})
self.product_refrigerator.categ_id.property_cost_method = 'fifo'
self.product_refrigerator.categ_id.property_valuation = 'real_time'
self.product_oven = self.Product.create({
'name': 'Microwave Oven',
'type': 'product',
'cost_method': 'fifo',
'valuation': 'real_time',
'standard_price': 1.0,
'weight': 20,
'volume': 1.5,
'categ_id': self.categ_all.id})
self.product_oven.categ_id.property_cost_method = 'fifo'
self.product_oven.categ_id.property_valuation = 'real_time'
# Create service type product 1.Labour 2.Brokerage 3.Transportation 4.Packaging
self.landed_cost = self._create_services('Landed Cost')
self.brokerage_quantity = self._create_services('Brokerage Cost')
self.transportation_weight = self._create_services('Transportation Cost')
self.packaging_volume = self._create_services('Packaging Cost')
# Ensure the account properties exists.
self.ensure_account_property('property_stock_account_input')
self.ensure_account_property('property_stock_account_output')
def _create_services(self, name):
return self.Product.create({
@@ -20,23 +20,21 @@ class TestStockLandedCosts(TestStockLandedCostsCommon):
# them for real_time valuation and fifo costing method
product_landed_cost_1 = self.env['product.product'].create({
'name': "LC product 1",
'cost_method': 'fifo',
'valuation': 'real_time',
'weight': 10,
'volume': 1,
'property_stock_account_input': self.ref('stock_landed_costs.o_expense'),
'property_stock_account_output': self.ref('stock_landed_costs.o_income'),
})
product_landed_cost_1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
product_landed_cost_1.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.ref('stock_landed_costs.o_expense')
product_landed_cost_1.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income')
product_landed_cost_2 = self.env['product.product'].create({
'name': "LC product 2",
'cost_method': 'fifo',
'valuation': 'real_time',
'weight': 20,
'volume': 1.5,
'property_stock_account_input': self.ref('stock_landed_costs.o_expense'),
'property_stock_account_output': self.ref('stock_landed_costs.o_income'),
})
product_landed_cost_2.product_tmpl_id.categ_id.property_cost_method = 'fifo'
product_landed_cost_2.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.ref('stock_landed_costs.o_expense')
product_landed_cost_2.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income')
picking_default_vals = self.env['stock.picking'].default_get(list(self.env['stock.picking'].fields_get()))
@@ -25,21 +25,20 @@ class TestStockLandedCostsRounding(TestStockLandedCostsCommon):
# valuation and real price costing method
product_landed_cost_3 = self.env['product.product'].create({
'name': "LC product 3",
'cost_method': 'fifo',
'uom_id': product_uom_unit_round_1.id,
'valuation': 'real_time',
'property_stock_account_input': self.ref('stock_landed_costs.o_expense'),
'property_stock_account_output': self.ref('stock_landed_costs.o_income'),
})
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.ref('stock_landed_costs.o_expense')
product_landed_cost_3.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income')
product_landed_cost_4 = self.env['product.product'].create({
'name': "LC product 4",
'cost_method': 'fifo',
'uom_id': product_uom_unit_round_1.id,
'valuation': 'real_time',
'property_stock_account_input': self.ref('stock_landed_costs.o_expense'),
'property_stock_account_output': self.ref('stock_landed_costs.o_income'),
})
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.ref('stock_landed_costs.o_expense')
product_landed_cost_4.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income')
picking_default_vals = self.env['stock.picking'].default_get(list(self.env['stock.picking'].fields_get()))