[ADD] stock_landed_costs: Add test case for incoming shipment.

The current test in landed costs puts landed costs on outgoing pickings.
It is a bit weird as they are put on incoming shipments normally.  It checks
if the lines of the landed costs have been calculated well, but not if the
amounts/accounts/... on the account move and account move lines have been
calculated correctly.  It should also check the entries created when some
part is already out and when we create negative landed costs.  (in order to
be able to revert them)

Scenario :
- Two new products without stock as is done in current test in real-time
  valuation,...
- Both products are received
- One product goes out (or a part of the quantity)
- A landed cost is created for the incoming picking
- Check that the journal items created, have the correct amounts and that there
  is a part that went out and is put on the out account
- Create a negative landed cost as the first landed cost was a little bit too high
- Check again that the journal items created have the correct amounts
This commit is contained in:
Virbhadrasinh Gohil
2016-03-23 11:27:55 +01:00
committed by Yannick Tivisse
parent 00f01b8b1d
commit 3855ab7d85
3 changed files with 318 additions and 0 deletions
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import test_stock_landed_costs_purchase
+67
View File
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from odoo.tests import common
class TestStockLandedCostsCommon(common.TransactionCase):
def setUp(self):
super(TestStockLandedCostsCommon, self).setUp()
# Objects
self.Product = self.env['product.product']
self.Picking = self.env['stock.picking']
self.Move = self.env['stock.move']
self.LandedCost = self.env['stock.landed.cost']
self.CostLine = self.env['stock.landed.cost.lines']
# References
self.supplier_id = self.ref('base.res_partner_2')
self.customer_id = self.ref('base.res_partner_4')
self.picking_type_in_id = self.ref('stock.picking_type_in')
self.picking_type_out_id = self.ref('stock.picking_type_out')
self.supplier_location_id = self.ref('stock.stock_location_suppliers')
self.stock_location_id = self.ref('stock.stock_location_stock')
self.customer_location_id = self.ref('stock.stock_location_customers')
self.categ_all = self.env.ref('product.product_category_all')
# Create account
self.default_account = self.env['account.account'].create({
'name': "Purchased Stocks",
'code': "X1101",
'user_type_id': self.env['account.account.type'].create({
'name': 'Expenses',
'type': 'other'}).id,
'reconcile': True})
self.expenses_journal = self.env['account.journal'].create({
'name': 'Expenses - Test',
'code': 'TEXJ',
'type': 'purchase',
'default_debit_account_id': self.default_account.id,
'default_credit_account_id': self.default_account.id})
# Create product refrigerator & oven
self.product_refrigerator = self.Product.create({
'name': 'Refrigerator',
'type': 'product',
'cost_method': 'real',
'valuation': 'real_time',
'standard_price': 1.0,
'weight': 10,
'volume': 1,
'categ_id': self.categ_all.id})
self.product_oven = self.Product.create({
'name': 'Microwave Oven',
'type': 'product',
'cost_method': 'real',
'valuation': 'real_time',
'standard_price': 1.0,
'weight': 20,
'volume': 1.5,
'categ_id': self.categ_all.id})
# 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')
def _create_services(self, name):
return self.Product.create({
'name': name,
'landed_cost_ok': True,
'type': 'service'})
@@ -0,0 +1,248 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo
from odoo.addons.stock_landed_costs.tests.common import TestStockLandedCostsCommon
@odoo.tests.common.at_install(False)
@odoo.tests.common.post_install(True)
class TestLandedCosts(TestStockLandedCostsCommon):
def setUp(self):
super(TestLandedCosts, self).setUp()
# Create picking incoming shipment
self.picking_in = self.Picking.create({
'partner_id': self.supplier_id,
'picking_type_id': self.picking_type_in_id,
'location_id': self.supplier_location_id,
'location_dest_id': self.stock_location_id})
self.Move.create({
'name': self.product_refrigerator.name,
'product_id': self.product_refrigerator.id,
'product_uom_qty': 5,
'product_uom': self.product_refrigerator.uom_id.id,
'picking_id': self.picking_in.id,
'location_id': self.supplier_location_id,
'location_dest_id': self.stock_location_id})
self.Move.create({
'name': self.product_oven.name,
'product_id': self.product_oven.id,
'product_uom_qty': 10,
'product_uom': self.product_oven.uom_id.id,
'picking_id': self.picking_in.id,
'location_id': self.supplier_location_id,
'location_dest_id': self.stock_location_id})
# Create picking outgoing shipment
self.picking_out = self.Picking.create({
'partner_id': self.customer_id,
'picking_type_id': self.picking_type_out_id,
'location_id': self.stock_location_id,
'location_dest_id': self.customer_location_id})
self.Move.create({
'name': self.product_refrigerator.name,
'product_id': self.product_refrigerator.id,
'product_uom_qty': 2,
'product_uom': self.product_refrigerator.uom_id.id,
'picking_id': self.picking_out.id,
'location_id': self.stock_location_id,
'location_dest_id': self.customer_location_id})
def test_00_landed_costs_on_incoming_shipment(self):
""" Test landed cost on incoming shipment """
#
# (A) Purchase product
# Services Quantity Weight Volume
# -----------------------------------------------------
# 1. Refrigerator 5 10 1
# 2. Oven 10 20 1.5
# (B) Add some costs on purchase
# Services Amount Split Method
# -------------------------------------------
# 1.labour 10 By Equal
# 2.brokerage 150 By Quantity
# 3.transportation 250 By Weight
# 4.packaging 20 By Volume
# Process incoming shipment
income_ship = self._process_incoming_shipment()
# Create landed costs
stock_landed_cost = self._create_landed_costs({
'equal_price_unit': 10,
'quantity_price_unit': 150,
'weight_price_unit': 250,
'volume_price_unit': 20}, income_ship)
# Compute landed costs
stock_landed_cost.compute_landed_cost()
valid_vals = {
'equal': 5.0,
'by_quantity_refrigerator': 50.0,
'by_quantity_oven': 100.0,
'by_weight_refrigerator': 50.0,
'by_weight_oven': 200,
'by_volume_refrigerator': 5.0,
'by_volume_oven': 15.0}
# Check valuation adjustment line recognized or not
self._validate_additional_landed_cost_lines(stock_landed_cost, valid_vals)
# Validate the landed cost.
stock_landed_cost.button_validate()
self.assertTrue(stock_landed_cost.account_move_id, 'Landed costs should be available account move lines')
account_entry = self.env['account.move.line'].read_group(
[('move_id', '=', stock_landed_cost.account_move_id.id)], ['debit', 'credit', 'move_id'], ['move_id'])[0]
self.assertEqual(account_entry['debit'], account_entry['credit'], 'Debit and credit are not equal')
self.assertEqual(account_entry['debit'], 430.0, 'Wrong Account Entry')
def test_01_negative_landed_costs_on_incoming_shipment(self):
""" Test negative landed cost on incoming shipment """
#
# (A) Purchase Product
# Services Quantity Weight Volume
# -----------------------------------------------------
# 1. Refrigerator 5 10 1
# 2. Oven 10 20 1.5
# (B) Sale refrigerator's part of the quantity
# (C) Add some costs on purchase
# Services Amount Split Method
# -------------------------------------------
# 1.labour 10 By Equal
# 2.brokerage 150 By Quantity
# 3.transportation 250 By Weight
# 4.packaging 20 By Volume
# (D) Decrease cost that already added on purchase
# (apply negative entry)
# Services Amount Split Method
# -------------------------------------------
# 1.labour -5 By Equal
# 2.brokerage -50 By Quantity
# 3.transportation -50 By Weight
# 4.packaging -5 By Volume
# Process incoming shipment
income_ship = self._process_incoming_shipment()
# Refrigerator outgoing shipment.
self._process_outgoing_shipment()
# Apply landed cost for incoming shipment.
stock_landed_cost = self._create_landed_costs({
'equal_price_unit': 10,
'quantity_price_unit': 150,
'weight_price_unit': 250,
'volume_price_unit': 20}, income_ship)
# Compute landed costs
stock_landed_cost.compute_landed_cost()
valid_vals = {
'equal': 5.0,
'by_quantity_refrigerator': 50.0,
'by_quantity_oven': 100.0,
'by_weight_refrigerator': 50.0,
'by_weight_oven': 200.0,
'by_volume_refrigerator': 5.0,
'by_volume_oven': 15.0}
# Check valuation adjustment line recognized or not
self._validate_additional_landed_cost_lines(stock_landed_cost, valid_vals)
# Validate the landed cost.
stock_landed_cost.button_validate()
self.assertTrue(stock_landed_cost.account_move_id, 'Landed costs should be available account move lines')
# Create negative landed cost for previously incoming shipment.
stock_negative_landed_cost = self._create_landed_costs({
'equal_price_unit': -5,
'quantity_price_unit': -50,
'weight_price_unit': -50,
'volume_price_unit': -5}, income_ship)
# Compute negative landed costs
stock_negative_landed_cost.compute_landed_cost()
valid_vals = {
'equal': -2.5,
'by_quantity_refrigerator': -16.67,
'by_quantity_oven': -33.33,
'by_weight_refrigerator': -10.00,
'by_weight_oven': -40.00,
'by_volume_refrigerator': -1.25,
'by_volume_oven': -3.75}
# Check valuation adjustment line recognized or not
self._validate_additional_landed_cost_lines(stock_negative_landed_cost, valid_vals)
# Validate the landed cost.
stock_negative_landed_cost.button_validate()
self.assertEqual(stock_negative_landed_cost.state, 'done', 'Negative landed costs should be in done state')
self.assertTrue(stock_negative_landed_cost.account_move_id, 'Landed costs should be available account move lines')
account_entry = self.env['account.move.line'].read_group(
[('move_id', '=', stock_negative_landed_cost.account_move_id.id)], ['debit', 'credit', 'move_id'], ['move_id'])[0]
self.assertEqual(account_entry['debit'], account_entry['credit'], 'Debit and credit are not equal')
self.assertEqual(account_entry['debit'], 122.168, 'Wrong Account Entry')
def _process_incoming_shipment(self):
""" Two product incoming shipment. """
# Confirm incoming shipment.
self.picking_in.action_confirm()
# Transfer incoming shipment
self.picking_in.do_transfer()
return self.picking_in
def _process_outgoing_shipment(self):
""" One product Outgoing shipment. """
# Confirm outgoing shipment.
self.picking_out.action_confirm()
# Product assign to outgoing shipments
self.picking_out.action_assign()
# Transfer picking.
self.picking_out.do_transfer()
def _create_landed_costs(self, value, picking_in):
return self.LandedCost.create(dict(
picking_ids=[(6, 0, [picking_in.id])],
account_journal_id=self.expenses_journal.id,
cost_lines=[
(0, 0, {
'name': 'equal split',
'split_method': 'equal',
'price_unit': value['equal_price_unit'],
'product_id': self.landed_cost.id}),
(0, 0, {
'name': 'split by quantity',
'split_method': 'by_quantity',
'price_unit': value['quantity_price_unit'],
'product_id': self.brokerage_quantity.id}),
(0, 0, {
'name': 'split by weight',
'split_method': 'by_weight',
'price_unit': value['weight_price_unit'],
'product_id': self.transportation_weight.id}),
(0, 0, {
'name': 'split by volume',
'split_method': 'by_volume',
'price_unit': value['volume_price_unit'],
'product_id': self.packaging_volume.id})
],
))
def _validate_additional_landed_cost_lines(self, stock_landed_cost, valid_vals):
for valuation in stock_landed_cost.valuation_adjustment_lines:
add_cost = valuation.additional_landed_cost
split_method = valuation.cost_line_id.split_method
product = valuation.move_id.product_id
if split_method == 'equal':
self.assertEqual(add_cost, valid_vals['equal'], self._error_message(valid_vals['equal'], add_cost))
elif split_method == 'by_quantity' and product == self.product_refrigerator:
self.assertEqual(add_cost, valid_vals['by_quantity_refrigerator'], self._error_message(valid_vals['by_quantity_refrigerator'], add_cost))
elif split_method == 'by_quantity' and product == self.product_oven:
self.assertEqual(add_cost, valid_vals['by_quantity_oven'], self._error_message(valid_vals['by_quantity_oven'], add_cost))
elif split_method == 'by_weight' and product == self.product_refrigerator:
self.assertEqual(add_cost, valid_vals['by_weight_refrigerator'], self._error_message(valid_vals['by_weight_refrigerator'], add_cost))
elif split_method == 'by_weight' and product == self.product_oven:
self.assertEqual(add_cost, valid_vals['by_weight_oven'], self._error_message(valid_vals['by_weight_oven'], add_cost))
elif split_method == 'by_volume' and product == self.product_refrigerator:
self.assertEqual(add_cost, valid_vals['by_volume_refrigerator'], self._error_message(valid_vals['by_volume_refrigerator'], add_cost))
elif split_method == 'by_volume' and product == self.product_oven:
self.assertEqual(add_cost, valid_vals['by_volume_oven'], self._error_message(valid_vals['by_volume_oven'], add_cost))
def _error_message(self, actucal_cost, computed_cost):
return 'Additional Landed Cost should be %s instead of %s' % (actucal_cost, computed_cost)