236 lines
9.3 KiB
Python
236 lines
9.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo.fields import Date, Datetime
|
|
from odoo.tools import mute_logger
|
|
from odoo.tests import Form, tagged
|
|
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
|
from odoo.addons.stock_account.tests.test_stockvaluation import _create_accounting_data
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestAngloSaxonValuationPurchaseMRP(AccountTestInvoicingCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls, chart_template_ref=None):
|
|
super().setUpClass(chart_template_ref=chart_template_ref)
|
|
cls.vendor01 = cls.env['res.partner'].create({'name': "Super Vendor"})
|
|
|
|
cls.stock_input_account, cls.stock_output_account, cls.stock_valuation_account, cls.expense_account, cls.stock_journal = _create_accounting_data(cls.env)
|
|
cls.avco_category = cls.env['product.category'].create({
|
|
'name': 'AVCO',
|
|
'property_cost_method': 'average',
|
|
'property_valuation': 'real_time',
|
|
'property_stock_account_input_categ_id': cls.stock_input_account.id,
|
|
'property_stock_account_output_categ_id': cls.stock_output_account.id,
|
|
'property_stock_journal': cls.stock_journal.id,
|
|
'property_stock_valuation_account_id': cls.stock_valuation_account.id,
|
|
})
|
|
|
|
currency_grp = cls.env.ref('base.group_multi_currency')
|
|
cls.env.user.write({'groups_id': [(4, currency_grp.id)]})
|
|
|
|
cls.env.company.anglo_saxon_accounting = True
|
|
|
|
def test_kit_anglo_saxo_price_diff(self):
|
|
"""
|
|
Suppose an automated-AVCO configuration and a Price Difference Account defined on
|
|
the product category. When buying a kit of that category at a higher price than its
|
|
cost, the difference should be published on the Price Difference Account
|
|
"""
|
|
kit, compo01, compo02 = self.env['product.product'].create([{
|
|
'name': name,
|
|
'standard_price': price,
|
|
'type': 'product',
|
|
'categ_id': self.avco_category.id,
|
|
} for name, price in [('Kit', 0), ('Compo 01', 10), ('Compo 02', 20)]])
|
|
|
|
self.env['mrp.bom'].create({
|
|
'product_tmpl_id': kit.product_tmpl_id.id,
|
|
'type': 'phantom',
|
|
'bom_line_ids': [(0, 0, {
|
|
'product_id': p.id,
|
|
'product_qty': 1,
|
|
}) for p in [compo01, compo02]]
|
|
})
|
|
kit.button_bom_cost()
|
|
|
|
po_form = Form(self.env['purchase.order'])
|
|
po_form.partner_id = self.vendor01
|
|
with po_form.order_line.new() as pol_form:
|
|
pol_form.product_id = kit
|
|
pol_form.price_unit = 100
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
po.picking_ids.button_validate()
|
|
|
|
action = po.action_create_invoice()
|
|
invoice = self.env['account.move'].browse(action['res_id'])
|
|
invoice.invoice_date = Date.today()
|
|
invoice.action_post()
|
|
|
|
svls = po.order_line.move_ids.stock_valuation_layer_ids
|
|
self.assertEqual(len(svls), 2, "The invoice should have created two SVL (one by kit's component) for the price diff")
|
|
self.assertEqual(sum(svls.mapped('value')), 100, "Should be the standard price of both components")
|
|
|
|
input_amls = self.env['account.move.line'].search([('account_id', '=', self.stock_input_account.id)])
|
|
self.assertEqual(sum(input_amls.mapped('balance')), 0)
|
|
|
|
def test_buy_deliver_and_return_kit_with_auto_avco_components(self):
|
|
"""
|
|
A kit K with two AVCO components
|
|
- C01, cost share 25%
|
|
- C02, cost share 75%
|
|
K in Units
|
|
C01, C02 in Litres
|
|
Buy and receive 1 kit @ 100
|
|
Deliver the kit
|
|
Update the cost shares
|
|
Return the delivery
|
|
"""
|
|
stock_location = self.env['stock.location'].search([
|
|
('company_id', '=', self.env.company.id),
|
|
('name', '=', 'Stock'),
|
|
])
|
|
customer_location = self.env.ref('stock.stock_location_customers')
|
|
type_out = self.env['stock.picking.type'].search([
|
|
('company_id', '=', self.env.company.id),
|
|
('name', '=', 'Delivery Orders')])
|
|
uom_unit = self.env.ref('uom.product_uom_unit')
|
|
uom_litre = self.env.ref('uom.product_uom_litre')
|
|
|
|
component01, component02 = self.env['product.product'].create([{
|
|
'name': 'Component %s' % name,
|
|
'type': 'product',
|
|
'categ_id': self.avco_category.id,
|
|
'uom_id': uom_litre.id,
|
|
'uom_po_id': uom_litre.id,
|
|
} for name in ['01', '02']])
|
|
|
|
kit = self.env['product.product'].create({
|
|
'name': 'Super Kit',
|
|
'type': 'consu',
|
|
'uom_id': uom_unit.id,
|
|
'uom_po_id': uom_unit.id,
|
|
})
|
|
|
|
bom_kit = self.env['mrp.bom'].create({
|
|
'product_tmpl_id': kit.product_tmpl_id.id,
|
|
'type': 'phantom',
|
|
'bom_line_ids': [(0, 0, {
|
|
'product_id': component01.id,
|
|
'product_qty': 1,
|
|
'cost_share': 25,
|
|
}), (0, 0, {
|
|
'product_id': component02.id,
|
|
'product_qty': 1,
|
|
'cost_share': 75,
|
|
})],
|
|
})
|
|
|
|
po_form = Form(self.env['purchase.order'])
|
|
po_form.partner_id = self.vendor01
|
|
with po_form.order_line.new() as pol_form:
|
|
pol_form.product_id = kit
|
|
pol_form.price_unit = 100
|
|
pol_form.taxes_id.clear()
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
receipt = po.picking_ids
|
|
receipt.move_line_ids.quantity = 1
|
|
receipt.button_validate()
|
|
|
|
self.assertEqual(receipt.state, 'done')
|
|
self.assertEqual(receipt.move_line_ids.product_id, component01 | component02)
|
|
self.assertEqual(po.order_line.qty_received, 1)
|
|
self.assertEqual(component01.stock_valuation_layer_ids.value, 25)
|
|
self.assertEqual(component02.stock_valuation_layer_ids.value, 75)
|
|
|
|
delivery = self.env['stock.picking'].create({
|
|
'picking_type_id': type_out.id,
|
|
'location_id': stock_location.id,
|
|
'location_dest_id': customer_location.id,
|
|
'move_ids': [(0, 0, {
|
|
'name': kit.name,
|
|
'product_id': kit.id,
|
|
'product_uom': kit.uom_id.id,
|
|
'product_uom_qty': 1.0,
|
|
'location_id': stock_location.id,
|
|
'location_dest_id': customer_location.id,
|
|
})],
|
|
})
|
|
delivery.action_confirm()
|
|
delivery.move_ids.move_line_ids.quantity = 1
|
|
delivery.button_validate()
|
|
|
|
self.assertEqual(component01.stock_valuation_layer_ids.mapped('value'), [25, -25])
|
|
self.assertEqual(component02.stock_valuation_layer_ids.mapped('value'), [75, -75])
|
|
|
|
with mute_logger('odoo.tests.form.onchange'):
|
|
with Form(bom_kit) as kit_form:
|
|
with kit_form.bom_line_ids.edit(0) as line:
|
|
line.cost_share = 30
|
|
with kit_form.bom_line_ids.edit(1) as line:
|
|
line.cost_share = 70
|
|
|
|
wizard_form = Form(self.env['stock.return.picking'].with_context(active_id=delivery.id, active_model='stock.picking'))
|
|
wizard = wizard_form.save()
|
|
action = wizard.create_returns()
|
|
return_picking = self.env["stock.picking"].browse(action["res_id"])
|
|
return_picking.move_ids.move_line_ids.quantity = 1
|
|
return_picking.button_validate()
|
|
|
|
self.assertEqual(component01.stock_valuation_layer_ids.mapped('value'), [25, -25, 25])
|
|
self.assertEqual(component02.stock_valuation_layer_ids.mapped('value'), [75, -75, 75])
|
|
|
|
def test_valuation_multicurrency_with_kits(self):
|
|
""" Purchase a Kit in multi-currency and verify that the amount_currency is correctly computed.
|
|
"""
|
|
|
|
# Setup Kit
|
|
kit, cmp = self.env['product.product'].create([{
|
|
'name': name,
|
|
'standard_price': 0,
|
|
'type': 'product',
|
|
'categ_id': self.avco_category.id,
|
|
} for name in ['Kit', 'Cmp']])
|
|
|
|
self.env['mrp.bom'].create({
|
|
'product_tmpl_id': kit.product_tmpl_id.id,
|
|
'type': 'phantom',
|
|
'bom_line_ids': [(0, 0, {'product_id': cmp.id, 'product_qty': 5})]
|
|
})
|
|
|
|
# Setup Currency
|
|
usd = self.env.ref('base.USD')
|
|
eur = self.env.ref('base.EUR')
|
|
self.env['res.currency.rate'].create({
|
|
'name': Datetime.today(),
|
|
'currency_id': usd.id,
|
|
'rate': 1})
|
|
self.env['res.currency.rate'].create({
|
|
'name': Datetime.today(),
|
|
'currency_id': eur.id,
|
|
'rate': 2})
|
|
|
|
# Create Purchase
|
|
po_form = Form(self.env['purchase.order'])
|
|
po_form.partner_id = self.vendor01
|
|
po_form.currency_id = eur
|
|
with po_form.order_line.new() as pol_form:
|
|
pol_form.product_id = kit
|
|
pol_form.price_unit = 100 # $50
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
po.picking_ids.button_validate()
|
|
|
|
svl = po.order_line.move_ids.stock_valuation_layer_ids.ensure_one()
|
|
input_aml = self.env['account.move.line'].search([('account_id', '=', self.stock_valuation_account.id)])
|
|
|
|
self.assertEqual(svl.value, 50) # USD
|
|
self.assertEqual(input_aml.amount_currency, 100) # EUR
|
|
self.assertEqual(input_aml.balance, 50) # USD
|