← Back to team overview

openerp-community-reviewer team mailing list archive

lp:~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge into lp:purchase-wkfl

 

You have been requested to review the proposed merge of lp:~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge into lp:purchase-wkfl.

For more details, see:
https://code.launchpad.net/~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge/+merge/190207

Hi there,

This MP adds the purchase_landed_cost module. This module bring the estimated landed costs related to a PO in the average price computation of the product.

It provides various way to enter them and distribute them accross all PO lines (see description of the module for more details). Thanks to Ferdinand Gasauer for the first version in C2C R&D addons and to Savoir Faire Linux to extract it in that branch. I made
quite a lot of changes:

 * Multi-currency properly handled (except the bug found regarding the price_type)
 * Clean the code
 * Make an option to chose or not the invoice generation by landed cost positions from the PO confirmation
 * Add a button to the see all landed cost position from PO
 * Add a reporting view to allow to compare by financial account the estimated cost with real one to allow the valuation of stock in the end of year.
 * Add comments and better description
 * Add tests

Thanks for review !

Regards,

Joël

-- 
https://code.launchpad.net/~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge/+merge/190207
Your team OpenERP Community Reviewer is requested to review the proposed merge of lp:~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge into lp:purchase-wkfl.
=== added directory 'purchase_landed_costs'
=== added file 'purchase_landed_costs/__init__.py'
--- purchase_landed_costs/__init__.py	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/__init__.py	2013-10-10 19:03:35 +0000
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#    
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2010-2013 Camptocamp (<http://www.camptocamp.com>)
+#    Authors: Ferdinand Gasauer, Joel Grand-Guillaume
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
+#
+##############################################################################
+
+
+from . import product
+from . import purchase
+from . import stock
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'purchase_landed_costs/__openerp__.py'
--- purchase_landed_costs/__openerp__.py	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/__openerp__.py	2013-10-10 19:03:35 +0000
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2010-2013 Camptocamp (<http://www.camptocamp.com>)
+#    Authors: Ferdinand Gasauer, Joel Grand-Guillaume
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+    'name': 'Purchase Landed Costs',
+    'version': '1.0',
+    'category': 'Warehouse Management',
+    'description': """
+Purchase Landed Costs
+=====================
+
+This module adds the possibility to include estimated landed costs to the average price computation. To define those landed costs, 
+create products for every landed costs and affect them a distribution type. Don't forget to as well assign them a specific 
+financial account (the one which will record the real cost) in order to compare at the end of the year the estimation with real
+accounting entries (see stock valuation). The landed costs is defined in purchase orders. These costs will be distributed 
+according to the distribution type defined in landed cost:
+
+ * value - example custom fees 
+ * quantity - example freight 
+
+Note : Products used to define landed cost must have a default "Distribution Type" set (Value/Quantity). 
+
+For each landed cost position (=line) define in a PO, a draft invoice can be pre-created at PO validation (an option need to 
+be checked). Doing so will allow you to see those invoices using the view invoice button directly from the PO. You can define 
+landed cost relative to a whole PO or by PO line (or both) and the system will distribute them to each line according to the 
+chosen distribution type.
+
+Note that the landed cost is always expressed in company currency.
+
+Find all landed cost here : Reporting -> Purchase -> Landed costs
+
+Stock valuation:
+----------------
+As the average price is also used for the stock valuation and because the computation is based on estimation of landed cost 
+in the PO (done at incoming shipment reception), you will have a  difference with the actual accounting bookings of landed cost. 
+Stock valuation will have to be adjusted with a manual journal entry. In order to correct that amount, make a sum of 
+estimated landed cost (landed cost position) by account and compare with the real account chart value. You can access those 
+informations through this menu: Reporting -> Purchase -> Landed costs
+
+Warning:
+--------
+
+ * Average price will be computed based on the estimation made on the PO - not from real cost. This is due to the way OpenERP
+   compute average stock : it stores the updated value at every input, no history, so no way to redefine the value afterwards. 
+   i.e.
+    - incomming 01: 100 product A at 50.- AVG = 50.-, stock = 100
+    - incomming 02: 100 product A at 60.- AVG = 55.-, stock = 200
+    - delivery 01: 50 product A AVG = 55.-, stock = 150
+    - Receive the real landed cost of 10.- for incomming 01 
+  => cannot compute back because no historical price was store for every transaction. Moreover, in OpenERP I can even 
+  set another average price for a product using the update wizard.
+
+
+ * As the price type of OpenERP is not really well handled, we need to be sure that price type of cost price in product form
+   is the same as the company one. Otherwise, when computing the AVG price, it make the convertion in company currency
+   from the price type currency. This is not related to this module, but from the core of OpenERP.
+   If you use this module in multi-company and different currency between company, you'll have to not share the product 
+   between them, even if product are the same.
+
+
+TODO/Ideas:
+-----------
+ * Manage multi-currencies landed costs in PO
+ * Have the shipped date in landed cost instead of PO date for a better analysis
+ * Compute a average purchase price per products while keep cost price as it is now
+""",
+    'author': 'Camptocamp',
+    'depends': ['purchase' ],
+    'website': 'http://www.camptocamp.com',
+    'data': ['security/ir.model.access.csv',
+             'security/landed_cost_security.xml',
+             'purchase_view.xml',
+            ],
+    'test': [
+        'test/landed_costs_based_on_quantity.yml',
+        'test/landed_costs_based_on_value.yml',
+        'test/landed_costs_on_qty_by_line_and_order.yml',
+        'test/landed_costs_multicurrency_pricelist.yml',
+        # those 2 tests here fails because of the bug regarding the price_type
+        # and average price computation in OpenERP. I'll keep them because
+        # The bug is happening when the company has a different currency that 
+        # the price_type of the standard_price field
+        # Unless you didn't have to do that, everything work fine.
+        # they should be sovled by a way or another.
+        #'test/landed_costs_multicurrency_company.yml',
+        #'test/landed_costs_multicurrency_pricetype.yml',
+    ],
+    'demo': [],
+    'installable': True,
+    'active': False,
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added directory 'purchase_landed_costs/i18n'
=== added file 'purchase_landed_costs/i18n/fr.po'
--- purchase_landed_costs/i18n/fr.po	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/i18n/fr.po	2013-10-10 19:03:35 +0000
@@ -0,0 +1,320 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* purchase_landed_costs
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-10-10 07:46+0000\n"
+"PO-Revision-Date: 2013-10-10 07:46+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_purchase_order_line
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_purchase_order_line_id
+#: field:landed.cost.position,purchase_order_line_id:0
+msgid "Purchase Order Line"
+msgstr "Ligne de commande d'achat"
+
+#. module: purchase_landed_costs
+#: selection:landed.cost.position,price_type:0
+msgid "Per Quantity"
+msgstr "Par Quantité"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_stock_move_price_unit_net
+#: field:stock.move,price_unit_net:0
+msgid "Purchase Price"
+msgstr "Prix d'achat"
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "None"
+msgstr "Aucun"
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Group By..."
+msgstr "Grouper Par..."
+
+#. module: purchase_landed_costs
+#: help:product.template,landed_cost_type:0
+msgid "Used if this product is landed costs: If landed costs are defined for purchase orders or pickings, this indicates how the costs are distributed to the lines"
+msgstr "Utilisé si ce produit est un coût d'acquisition: Si des coûts d'acquisition sont définis sur les commandes d'achat ou les bons de livraison, ceci indique la répartion de ces coûts sur les lignes"
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Supplier"
+msgstr "Fournisseurs"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_generate_invoice
+#: field:landed.cost.position,generate_invoice:0
+msgid "Generate Invoice"
+msgstr "Generer la facture"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_landed_cost_position
+msgid "landed.cost.position"
+msgstr "landed.cost.position"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_account_id
+#: field:landed.cost.position,account_id:0
+msgid "Fiscal Account"
+msgstr "Compte"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,partner_id:0
+msgid "The supplier of this cost component."
+msgstr "Fournisseur lié à ce coût d'acquisition"
+
+#. module: purchase_landed_costs
+#: selection:landed.cost.position,price_type:0
+msgid "Absolute Value"
+msgstr "Valeur"
+
+#. module: purchase_landed_costs
+#: code:addons/purchase_landed_costs/product.py:66
+#, python-format
+msgid "Define expense account for this company: \"%s\" (id:%d)."
+msgstr "Define expense account for this company: \"%s\" (id:%d)."
+
+#. module: purchase_landed_costs
+#: code:addons/purchase_landed_costs/purchase.py:372
+#, python-format
+msgid "Define purchase journal for this company: \"%s\" (id:%d)."
+msgstr "Definit un journal d'achat pour cette société: \"%s\" (id:%d)."
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost_line_ids
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landed_costs
+#: view:landed.cost.position:0
+#: field:purchase.order,landed_cost_line_ids:0
+#: field:purchase.order.line,landed_costs:0
+msgid "Landed Costs"
+msgstr "Coûts d'acquisition"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_company_id
+#: field:landed.cost.position,company_id:0
+msgid "Company"
+msgstr "Société"
+
+#. module: purchase_landed_costs
+#: model:ir.actions.act_window,name:purchase_landed_costs.act_po_2_landed_costs
+msgid "Related Landed Costs"
+msgstr "Coûts d'acquisition liés"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_date_po
+#: view:landed.cost.position:0
+#: field:landed.cost.position,date_po:0
+msgid "Date"
+msgstr "Date"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost_base_value
+#: field:purchase.order,landed_cost_base_value:0
+msgid "Landed Costs Base Value"
+msgstr "Coûts d'acquisition valeur de base"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landing_cost_lines
+#: field:purchase.order,landing_cost_lines:0
+msgid "Landing Cost Lines"
+msgstr "Lignes de coût d'acquisition"
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Purchase"
+msgstr "Achat"
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Account"
+msgstr "Compte"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_price_type
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_product_template_landed_cost_type
+#: field:landed.cost.position,price_type:0
+#: field:product.template,landed_cost_type:0
+msgid "Distribution Type"
+msgstr "Type de Distribution"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,amount:0
+msgid "Landed cost for stock valuation (expressed in company default currency). It will be added to the price of the supplier price."
+msgstr "Coût d'acquisition pour la valorisation des stocks (exprimés en devise de la société). S'ajoutera au coût de revient (prix moyen ou Standard)."
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Total amount"
+msgstr "Montant Total"
+
+#. module: purchase_landed_costs
+#: model:ir.actions.act_window,help:purchase_landed_costs.action_landed_cost_report_all
+msgid "Landed cost Analysis allows you to easily check and analyse your estimated landed costs."
+msgstr "L'analyse des coûts d'acquisition permet de contrôler les estimations de coût d'acquisition des commandes d'achat."
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_product_product
+#: view:landed.cost.position:0
+msgid "Product"
+msgstr "Produit"
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "Value"
+msgstr "Valeur"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_purchase_order
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_purchase_order_id
+#: field:landed.cost.position,purchase_order_id:0
+msgid "Purchase Order"
+msgstr "Bon de commande"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landed_cost_line_ids
+#: field:purchase.order.line,landed_cost_line_ids:0
+msgid "Landed Costs Positions"
+msgstr "Positions de coûts d'acquisition"
+
+#. module: purchase_landed_costs
+#: code:addons/purchase_landed_costs/product.py:65
+#: code:addons/purchase_landed_costs/purchase.py:371
+#, python-format
+msgid "Error!"
+msgstr "Erreur!"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_amount
+#: field:landed.cost.position,amount:0
+msgid "Amount"
+msgstr "Montant"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_quantity_total
+#: field:purchase.order,quantity_total:0
+msgid "Total Quantity"
+msgstr "Quantité totale"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,amount_total:0
+msgid "This field represent the total amount of this position regarding a whole order. By summing it, you'll have the total landed cost for the order"
+msgstr "Ce champs représente de montant total de cette position par rapport à l'ensemble du bon de commande. En l'additionnant, vous obtiendrez le total des coûts d'acquisition pour ce bon de commande."
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_partial_picking
+msgid "Partial Picking Processing Wizard"
+msgstr "Assistant de livraison partielle"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,date_po:0
+msgid "Date of the related PO"
+msgstr "Date du bon de commande lié"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,generate_invoice:0
+msgid "If ticked, this will generate a draft invoice at the PO confirmation for this landed cost position from the related partner. If not, no invoice will be generated, but the cost will be included for the average price computation."
+msgstr "Si coché, une facture brouillon (donc modifiable) sera pré-générée lors de la confirmation du bon de commande pour cette position de coût d'acquisition graĉe au fournisseur lié. Si non cochée, aucune facture ne sera pré-générée mais le coût de revient sera calculé en tenant compte des coûts d'acquisiton tout de même."
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,price_type:0
+msgid "Defines if the amount is to be calculated for each quantity or an absolute value"
+msgstr "Definit si le montant du coût d'acquisition est réparti selon les quantités ou les valeurs."
+
+#. module: purchase_landed_costs
+#: model:ir.actions.act_window,name:purchase_landed_costs.action_landed_cost_report_all
+#: model:ir.ui.menu,name:purchase_landed_costs.menu_action_landed_cost_report_all
+msgid "Landed Costs Analysis"
+msgstr "Analyse des coûts d'acquisiton"
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "Quantity"
+msgstr "Quantité"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_product_id
+#: field:landed.cost.position,product_id:0
+msgid "Landed Cost Name"
+msgstr "Nom du coût d'acquisiton"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost_base_quantity
+#: field:purchase.order,landed_cost_base_quantity:0
+msgid "Landed Costs Base Quantity"
+msgstr "Quantité de base du coûts d'acquisiton"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landing_costs_order
+#: field:purchase.order.line,landing_costs_order:0
+msgid "Landing Costs from Order"
+msgstr "Coûts d'acquisiton de la commande"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_move
+msgid "Stock Move"
+msgstr "Mouvement de stock"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_product_template
+msgid "Product Template"
+msgstr "Modèle d'article"
+
+#. module: purchase_landed_costs
+#: help:stock.move,price_unit_net:0
+msgid "This is the net purchase price, without landed cost as the price include landed price has been stored in price_unit field"
+msgstr "Il s'agit du prix d'achat net (sans coûts d'acquisiton). Le coût de revient (avec coûts d'acquisiton) est stocké dans le champs Prix Unitaire "
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Purchase Line"
+msgstr "Ligne d'achat"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_partner_id
+#: field:landed.cost.position,partner_id:0
+msgid "Partner"
+msgstr "Partenaire"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost
+#: field:purchase.order,landed_cost:0
+msgid "Landed Costs Total Untaxed"
+msgstr "Coûts d'acquisiton H.T total"
+
+#. module: purchase_landed_costs
+#: view:purchase.order:0
+msgid "Open All Landed costs"
+msgstr "Ouvrir tout les coûts d'acquisiton"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landing_costs
+#: view:landed.cost.position:0
+#: view:purchase.order:0
+#: view:purchase.order.line:0
+#: field:purchase.order.line,landing_costs:0
+msgid "Landing Costs"
+msgstr "Coûts d'acquisiton"
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_amount_total
+#: field:landed.cost.position,amount_total:0
+msgid "Amount Total"
+msgstr "Montant total"
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Purchase Orders"
+msgstr "Bon de commande"
+

=== added file 'purchase_landed_costs/i18n/purchase_landed_costs.pot'
--- purchase_landed_costs/i18n/purchase_landed_costs.pot	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/i18n/purchase_landed_costs.pot	2013-10-10 19:03:35 +0000
@@ -0,0 +1,318 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* purchase_landed_costs
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-10-09 17:43+0000\n"
+"PO-Revision-Date: 2013-10-09 17:43+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_purchase_order_line
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_purchase_order_line_id
+#: field:landed.cost.position,purchase_order_line_id:0
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: selection:landed.cost.position,price_type:0
+msgid "Per Quantity"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_stock_move_price_unit_net
+#: field:stock.move,price_unit_net:0
+msgid "Purchase Price"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "None"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Group By..."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:product.template,landed_cost_type:0
+msgid "Used if this product is landed costs: If landed costs are defined for purchase orders or pickings, this indicates how the costs are distributed to the lines"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Supplier"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_generate_invoice
+#: field:landed.cost.position,generate_invoice:0
+msgid "Generate Invoice"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_landed_cost_position
+msgid "landed.cost.position"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_account_id
+#: field:landed.cost.position,account_id:0
+msgid "Fiscal Account"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,partner_id:0
+msgid "The supplier of this cost component."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: selection:landed.cost.position,price_type:0
+msgid "Absolute Value"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: code:addons/purchase_landed_costs/product.py:66
+#, python-format
+msgid "Define expense account for this company: \"%s\" (id:%d)."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: code:addons/purchase_landed_costs/purchase.py:372
+#, python-format
+msgid "Define purchase journal for this company: \"%s\" (id:%d)."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost_line_ids
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landed_costs
+#: field:purchase.order,landed_cost_line_ids:0
+#: field:purchase.order.line,landed_costs:0
+msgid "Landed Costs"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_company_id
+#: field:landed.cost.position,company_id:0
+msgid "Company"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.actions.act_window,name:purchase_landed_costs.act_po_2_landed_costs
+msgid "Related Landed Costs"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_date_po
+#: view:landed.cost.position:0
+#: field:landed.cost.position,date_po:0
+msgid "Date"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost_base_value
+#: field:purchase.order,landed_cost_base_value:0
+msgid "Landed Costs Base Value"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landing_cost_lines
+#: field:purchase.order,landing_cost_lines:0
+msgid "Landing Cost Lines"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Purchase"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Account"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_price_type
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_product_template_landed_cost_type
+#: field:landed.cost.position,price_type:0
+#: field:product.template,landed_cost_type:0
+msgid "Distribution Type"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,amount:0
+msgid "Landed cost for stock valuation (expressed in company default currency). It will be added to the price of the supplier price."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Total amount"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.actions.act_window,help:purchase_landed_costs.action_landed_cost_report_all
+msgid "Landed cost Analysis allows you to easily check and analyse your estimated landed costs."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_product_product
+#: view:landed.cost.position:0
+msgid "Product"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "Value"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_purchase_order
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_purchase_order_id
+#: field:landed.cost.position,purchase_order_id:0
+msgid "Purchase Order"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landed_cost_line_ids
+#: field:purchase.order.line,landed_cost_line_ids:0
+msgid "Landed Costs Positions"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: code:addons/purchase_landed_costs/product.py:65
+#: code:addons/purchase_landed_costs/purchase.py:371
+#, python-format
+msgid "Error!"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_amount
+#: field:landed.cost.position,amount:0
+msgid "Amount"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_quantity_total
+#: field:purchase.order,quantity_total:0
+msgid "Total Quantity"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,amount_total:0
+msgid "This field represent the total amount of this position regarding a whole order. By summing it, you'll have the total landed cost for the order"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_partial_picking
+msgid "Partial Picking Processing Wizard"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,date_po:0
+msgid "Date of the related PO"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,generate_invoice:0
+msgid "If ticked, this will generate a draft invoice at the PO confirmation for this landed cost position from the related partner. If not, no invoice will be generated, but the cost will be included for the average price computation."
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,price_type:0
+msgid "Defines if the amount is to be calculated for each quantity or an absolute value"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.actions.act_window,name:purchase_landed_costs.action_landed_cost_report_all
+#: model:ir.ui.menu,name:purchase_landed_costs.menu_action_landed_cost_report_all
+msgid "Landed Costs Analysis"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "Quantity"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_product_id
+#: field:landed.cost.position,product_id:0
+msgid "Landed Cost Name"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost_base_quantity
+#: field:purchase.order,landed_cost_base_quantity:0
+msgid "Landed Costs Base Quantity"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landing_costs_order
+#: field:purchase.order.line,landing_costs_order:0
+msgid "Landing Costs from Order"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_move
+msgid "Stock Move"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_product_template
+msgid "Product Template"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: help:stock.move,price_unit_net:0
+msgid "This is the net purchase price, without landed cost as the price include landed price has been stored in price_unit field"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Purchase Line"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_partner_id
+#: field:landed.cost.position,partner_id:0
+msgid "Partner"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_landed_cost
+#: field:purchase.order,landed_cost:0
+msgid "Landed Costs Total Untaxed"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:purchase.order:0
+msgid "Open All Landed costs"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_purchase_order_line_landing_costs
+#: view:landed.cost.position:0
+#: view:purchase.order:0
+#: view:purchase.order.line:0
+#: field:purchase.order.line,landing_costs:0
+msgid "Landing Costs"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: model:ir.model.fields,field_description:purchase_landed_costs.field_landed_cost_position_amount_total
+#: field:landed.cost.position,amount_total:0
+msgid "Amount Total"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0
+msgid "Purchase Orders"
+msgstr ""

=== added file 'purchase_landed_costs/product.py'
--- purchase_landed_costs/product.py	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/product.py	2013-10-10 19:03:35 +0000
@@ -0,0 +1,73 @@
+#  -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2010-2013 Camptocamp (<http://www.camptocamp.com>)
+#    Authors: Ferdinand Gasauer, Joel Grand-Guillaume
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from tools.translate import _
+        
+
+class product_template(orm.Model):
+    _inherit = "product.template"
+
+    _columns = {
+        'landed_cost_type': fields.selection(
+            [('value','Value'),
+             ('per_unit','Quantity'),
+             ('none','None')],
+            'Distribution Type',
+            help="Used if this product is landed costs: "
+                 "If landed costs are defined for purchase orders or pickings, "
+                 "this indicates how the costs are distributed to the lines"),
+    }
+
+    _defaults = {
+        'landed_cost_type': lambda self, cr, uid, context: 
+            context['landed_cost_type'] if 'landed_cost_type'\
+                in context else None
+    } 
+
+
+class product_product(orm.Model):
+    _inherit = "product.product"
+
+    def _choose_exp_account_from(self, cr, uid, product, fiscal_position=False,
+             context=None):
+        """Method to compute the expense account to chose based on product and 
+        fiscal position. Used in invoice creation and on_change of landed costs.
+        Taken from method : _choose_account_from_po_line of purchase.py in 
+        purchase module."""
+        fiscal_obj = self.pool.get('account.fiscal.position')
+        property_obj = self.pool.get('ir.property')
+        if product:
+            acc_id = product.property_account_expense.id
+            if not acc_id:
+                acc_id = product.categ_id.property_account_expense_categ.id
+            if not acc_id:
+                raise osv.except_osv(
+                    _('Error!'),
+                    _('Define expense account for this company: "%s" (id:%d).') 
+                        % (product.name, product.id,))
+        else:
+            acc_id = property_obj.get(cr, uid, 
+                'property_account_expense_categ', 'product.category').id
+        return fiscal_obj.map_account(cr, uid, fiscal_position, acc_id)
+
+

=== added file 'purchase_landed_costs/purchase.py'
--- purchase_landed_costs/purchase.py	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/purchase.py	2013-10-10 19:03:35 +0000
@@ -0,0 +1,518 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2010-2013 Camptocamp (<http://www.camptocamp.com>)
+#    Authors: Ferdinand Gasauer, Joel Grand-Guillaume
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+from tools.translate import _
+import logging
+
+
+class landed_cost_position(orm.Model):
+    """The landed cost position represent a direct cost for the delivery 
+    of the goods puchased. It can be from a different partner than the 
+    original supplier, like transport. Cost will be re-affected to each PO line
+    in respect of the distribution method selected. The average price 
+    computation for the product will take those direct costs into account."""
+
+    _name = "landed.cost.position"
+
+    def _get_company_currency_from_landed_cost(self, cr, uid, 
+            landed_cost, amount, context=None):
+        """Return the amount in company currency by looking at the po. always
+        return a value, even if company currency = PO one.
+        :param browse_record landed_cost: Landed cost position browse record
+        :param float value to convert
+        :return: Float value amount in company currency converted at po date"""
+        cur_obj = self.pool.get('res.currency')
+        cmp_cur_id = landed_cost.purchase_order_id.company_id.currency_id.id
+        po_cur_id = landed_cost.purchase_order_id.pricelist_id.currency_id.id
+        result = 0.0
+        # Always provide the amount in currency
+        if cmp_cur_id == po_cur_id:
+            result = amount
+        else:
+            ctx = context.copy()
+            ctx['date'] = landed_cost.date_po or False
+            result = cur_obj.compute(cr, uid,
+                                     po_cur_id,
+                                     cmp_cur_id,
+                                     amount,
+                                     context=ctx)
+        return result
+
+    def _get_total_amount(self, cr, uid, landed_cost, context=None):
+        """We should have a field that is the computed value (total costs that land)
+        e.g. if it's related to a line and per_unit => I want for the reporting
+        the total line landed cost and multiply the quantity by given amount.
+        :param browse_record landed_cost: Landed cost position browse record
+        :return total value of this landed cost position"""
+        vals_po_currency = 0.0
+        if landed_cost.purchase_order_line_id and landed_cost.price_type == 'per_unit':
+            vals_po_currency = (landed_cost.amount * 
+                landed_cost.purchase_order_line_id.product_qty)
+        else:
+            vals_po_currency = landed_cost.amount
+        return vals_po_currency
+
+    def _get_amounts(self, cr, uid, ids, field_name, arg, context=None):
+        if not ids : return {}
+        if context is None:
+            context = {}
+        result = {}
+        for landed_cost in self.browse(cr, uid, ids, context=context):
+            val_comp_currency = self._get_company_currency_from_landed_cost(cr, uid, 
+                        landed_cost, landed_cost.amount, context=context)
+            val_total = self._get_total_amount(cr, uid, landed_cost, 
+                context=context)
+            val_total_comp_currency = self._get_company_currency_from_landed_cost(cr, uid, 
+                        landed_cost, val_total, context=context)
+            amounts = {'amount_company_currency': val_comp_currency,
+                'amount_total': val_total,
+                'amount_total_comp_currency': val_total_comp_currency}
+            result[landed_cost.id] = amounts
+        return result
+
+    def _get_po(self, cr, uid, ids, context=None):
+        landed_obj = self.pool.get('landed.cost.position')
+        return landed_obj.search(cr, uid,
+                                  [('purchase_order_id', 'in', ids)],
+                                  context=context)
+
+    _columns = {
+        'product_id': fields.many2one(
+            'product.product',
+            'Landed Cost Name',
+            required=True,
+            domain=[('landed_cost_type','!=', False)]),
+        'account_id': fields.many2one(
+            'account.account',
+            'Fiscal Account',
+            required=True,),
+        'partner_id': fields.many2one(
+            'res.partner',
+            'Partner',
+            help="The supplier of this cost component.",
+            required=True),
+        'price_type': fields.selection(
+            [('per_unit','Per Quantity'),
+             ('value','Absolute Value')],
+            'Distribution Type',
+            required=True,
+            help="Defines if the amount is to be calculated for each quantity "
+                 "or an absolute value"),
+        'purchase_order_line_id': fields.many2one(
+            'purchase.order.line',
+            'Purchase Order Line'),
+        'purchase_order_id': fields.many2one('purchase.order', 'Purchase Order'),
+        'generate_invoice': fields.boolean(
+            'Generate Invoice',
+            help="If ticked, this will generate a draft invoice at the PO confirmation "
+                 "for this landed cost position from the related partner. If not, no "
+                 "invoice will be generated, but the cost will be included for the average "
+                 "price computation."),
+        'amount': fields.float
+            ('Amount',
+            required=True,
+            digits_compute=dp.get_precision('Purchase Price'),
+            help="Landed cost expressed in PO currency used to fullfil landed cost."),
+        'amount_company_currency': fields.function(
+            _get_amounts,
+            type="float",
+            multi='compute_amounts',
+            string='Amount Company Currency',
+            # Use Account as it's for comparison with financial accounting
+            digits_compute=dp.get_precision('Account'),
+            store={
+                'purchase.order': (_get_po,
+                                   ['pricelist_id', 'company_id'], 50),
+                'landed.cost.position': (lambda self, cr, uid, ids, c=None: ids,
+                                          ['amount','purchase_order_id'], 10),
+            },
+            help="Landed cost for stock valuation (expressed in company currency). "
+                 "It will be added to the price of the supplier price."),
+        'amount_total': fields.function(
+            _get_amounts,
+            type="float",
+            multi='compute_amounts',
+            digits_compute=dp.get_precision('Purchase Price'),
+            string='Amount Total',
+            help="This field represent the total amount of this position "
+                 "regarding a whole order. By summing it, you'll have the total "
+                 "landed cost for the order (in his currency)",
+            store={
+                'purchase.order': (_get_po,
+                                   ['pricelist_id', 'company_id'], 50),
+                'landed.cost.position': (lambda self, cr, uid, ids, c=None: ids,
+                                          ['amount','purchase_order_id'], 10),},
+            ),
+        'amount_total_comp_currency': fields.function(
+            _get_amounts,
+            type="float",
+            multi='compute_amounts',
+            digits_compute=dp.get_precision('Account'),
+            string='Amount Total Company Currency',
+            help="This field represent the total amount of this position "
+                 "regarding a whole order. By summing it, you'll have the total "
+                 "landed cost for the order (in company reference currency).",
+            store={
+                'purchase.order': (_get_po,
+                                   ['pricelist_id', 'company_id'], 50),
+                'landed.cost.position': (lambda self, cr, uid, ids, c=None: ids,
+                                          ['amount','purchase_order_id'], 10),},
+            ),
+        'date_po': fields.related('purchase_order_id', 'date_order', type='date',
+            string='Date',
+            store=True,
+            readonly=True,
+            help="Date of the related PO"),
+        'company_id': fields.many2one('res.company','Company',
+            required=True,
+            select=1,),
+      }
+
+    _default = {
+        'generate_invoice': False,
+        'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(
+            cr, uid, 'purchase.order', context=c),
+    }
+
+    def write(self, cr, uid, ids, vals, context=None):
+        """Add the purchase_order_id if only linked to a line"""
+        if vals.get('purchase_order_line_id'):
+            po = self.pool.get('purchase.order.line').browse(cr, uid, 
+                vals['purchase_order_line_id'], context=context).order_id
+            vals['purchase_order_id'] = po.id
+        return super(landed_cost_position, self).write(cr, uid, ids, 
+            vals, context=context)
+
+    def create(self, cr, uid, vals, context=None):
+        """Add the purchase_order_id if only linked to a line"""
+        if vals.get('purchase_order_line_id'):
+            po = self.pool.get('purchase.order.line').browse(cr, uid, 
+                vals['purchase_order_line_id'], context=context).order_id
+            vals['purchase_order_id'] = po.id
+        return super(landed_cost_position, self).create(cr, uid, vals, 
+            context=context)
+
+    def onchange_product_id(self, cr, uid, ids, product_id, 
+            purchase_order_id=False, context=None):
+        res = {}
+        fiscal_position = False
+        if product_id:
+            prod_obj = self.pool.get('product.product')
+            prod = prod_obj.browse(cr, uid, [product_id], context=context)[0]
+            if purchase_order_id:
+                po_obj = self.pool.get('purchase.order')
+                po = po_obj.browse(cr, uid, [purchase_order_id], context=context)[0]
+                fiscal_position = po.fiscal_position or False
+            account_id = prod_obj._choose_exp_account_from(cr, uid, prod, 
+                fiscal_position=fiscal_position, context=context)
+            value = {
+                'price_type': prod.landed_cost_type,
+                'account_id': account_id}
+            res = {'value': value}
+        return res
+
+
+class purchase_order_line(orm.Model):
+    _inherit = "purchase.order.line"
+
+    def _landing_cost(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        # landed costss for the line
+        for line in self.browse(cr, uid, ids):
+            landed_costs = 0.0
+            if line.landed_cost_line_ids:
+                for costs in line.landed_cost_line_ids:
+                    if costs.price_type == 'value':
+                        landed_costs += costs.amount
+                    else:       
+                        landed_costs += costs.amount * line.product_qty
+            result[line.id] = landed_costs
+        return result
+
+    def _landing_cost_order(self, cr, uid, ids, name, args, context):
+        if not ids:
+            return {}
+        result = {}
+        lines = self.browse(cr, uid, ids)
+        # Landed costs line by line
+        for line in lines:
+            landed_costs = 0.0
+            order = line.order_id
+            # distribution of landed costs of PO
+            if order.landed_cost_line_ids:
+                # Base value (Absolute Value)
+                if order.landed_cost_base_value:
+                    landed_costs += (order.landed_cost_base_value / 
+                                 order.amount_untaxed * line.price_subtotal)
+                # Base quantity (Per Quantity)
+                if order.landed_cost_base_quantity:
+                    landed_costs += (order.landed_cost_base_quantity / 
+                                 order.quantity_total * line.product_qty)
+            result[line.id] = landed_costs
+        return result
+
+    def _landed_cost(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        # landed costss for the line
+        for line in self.browse(cr, uid, ids):
+            landed_costs = 0.0
+            landed_costs += (line.price_subtotal + 
+                             line.landing_costs +  line.landing_costs_order)
+            result[line.id] = landed_costs
+        return result
+        
+    _columns = {
+         'landed_cost_line_ids': fields.one2many(
+            'landed.cost.position',
+            'purchase_order_line_id',
+            'Landed Costs Positions'),
+         'landing_costs': fields.function(
+            _landing_cost,
+            digits_compute=dp.get_precision('Account'),
+            string='Landing Costs'),
+         'landing_costs_order': fields.function(
+            _landing_cost_order,
+            digits_compute=dp.get_precision('Account'),
+            string='Landing Costs from Order'),
+         'landed_costs': fields.function(
+            _landed_cost,
+            digits_compute=dp.get_precision('Account'),
+            string='Landed Costs'),
+    }
+
+
+class purchase_order(orm.Model):
+    _inherit = "purchase.order"
+    _logger = logging.getLogger(__name__)
+
+    def _landed_cost_base_value(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        landed_costs_base_value = 0.0
+        for line in self.browse(cr, uid, ids):
+            if line.landed_cost_line_ids:
+                for costs in line.landed_cost_line_ids:
+                    if costs.price_type == 'value':
+                        landed_costs_base_value += costs.amount
+            result[line.id] = landed_costs_base_value
+        return result
+
+    def _landed_cost_base_quantity(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        landed_costs_base_quantity = 0.0
+        for line in self.browse(cr, uid, ids):
+            if line.landed_cost_line_ids:
+                for costs in line.landed_cost_line_ids:
+                    if costs.price_type == 'per_unit':
+                         landed_costs_base_quantity += costs.amount
+            result[line.id] = landed_costs_base_quantity
+        return result
+
+    def _quantity_total(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        quantity_total = 0.0
+        for line in self.browse(cr, uid, ids):
+            if line.order_line:
+                for pol in line.order_line:
+                    if pol.product_qty > 0.0:
+                         quantity_total += pol.product_qty
+            result[line.id] = quantity_total
+        return result
+
+    def _landed_cost(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        landed_costs = 0.0
+        # landed costss for the line
+        for line in self.browse(cr, uid, ids):
+            landed_costs += (line.landing_cost_lines + line.landed_cost_base_value + 
+                             line.landed_cost_base_quantity + line.amount_untaxed)
+            result[line.id] = landed_costs
+        return result
+
+    def _landing_cost_lines(self, cr, uid, ids, name, args, context):
+        if not ids : return {}
+        result = {}
+        landed_cost_lines = 0.0
+        for line in self.browse(cr, uid, ids):
+            if line.order_line:
+                for pol in line.order_line:
+                    if pol.product_qty > 0.0:
+                         landed_cost_lines += pol.landing_costs
+            result[line.id] = landed_cost_lines
+        return result
+
+    _columns = {
+         'landed_cost_line_ids': fields.one2many(
+            'landed.cost.position',
+            'purchase_order_id',
+            'Landed Costs',
+            domain=[('purchase_order_line_id','=',False)]),
+         'landed_cost_base_value': fields.function(
+            _landed_cost_base_value,
+            digits_compute=dp.get_precision('Account'), 
+            string='Landed Costs Base Value'),
+         'landed_cost_base_quantity': fields.function(
+            _landed_cost_base_quantity,
+            digits_compute=dp.get_precision('Account'),
+            string='Landed Costs Base Quantity'),
+         'landing_cost_lines': fields.function(
+            _landing_cost_lines,
+            digits_compute=dp.get_precision('Account'),
+            string='Landing Cost Lines'),
+         'landed_cost': fields.function(
+            _landed_cost,
+            digits_compute=dp.get_precision('Account'),
+            string='Landed Costs Total Untaxed'),
+         'quantity_total': fields.function(
+            _quantity_total,
+            digits_compute=dp.get_precision('Product UoM'),
+            string='Total Quantity'),
+    }
+
+    def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id,
+            context=None):
+        """Here, the technical price_unit field will store the purchase price + 
+        landed cost. The original purchase price is stored in price_unit_net new
+        field to keep record of it."""
+        res = super(purchase_order,self)._prepare_order_line_move(cr, uid, order, 
+            order_line, picking_id, context=context)
+        res['price_unit_net'] =  res['price_unit']
+        res['price_unit'] = order_line.landed_costs / order_line.product_qty        
+        return res
+
+    def _prepare_landed_cost_inv_line(self, cr, uid, account_id, inv_id, 
+            landed_cost, context=None):
+        """Collects require data from landed cost position that is used to 
+        create invoice line for that particular position.
+        If it comes from a PO line and Distribution type is per unit
+        the quantity of the invoice is the PO line quantity
+        :param account_id: Expense account.
+        :param inv_id: Related invoice.
+        :param browse_record landed_cost: Landed cost position browse record
+        :return: Value for fields of invoice lines.
+        :rtype: dict
+        """
+        qty = 1.0
+        if (landed_cost.purchase_order_line_id and 
+            landed_cost.price_type == 'per_unit'):
+            qty = landed_cost.purchase_order_line_id.product_qty
+        return {
+            'name': landed_cost.product_id.name,
+            'account_id': account_id,
+            'invoice_id' : inv_id,
+            'price_unit': landed_cost.amount or 0.0,
+            'quantity': qty,
+            'product_id': landed_cost.product_id.id or False,
+            'invoice_line_tax_id': [(6, 0, [x.id for x in 
+                landed_cost.product_id.supplier_taxes_id])],
+        }
+
+    def _prepare_landed_cost_inv(self, cr, uid, landed_cost, context=None):
+        """Collects require data from landed cost position that is used to
+        create invoice for that particular position. Note that _landed
+        can come from a line or at whole PO level.
+        :param browse_record landed_cost: Landed cost position browse record
+        :return: Value for fields of invoice.
+        :rtype: dict
+        """
+        po = (landed_cost.purchase_order_id or
+            landed_cost.purchase_order_line_id.order_id)
+        currency_id = landed_cost.purchase_order_id.pricelist_id.currency_id.id
+        fiscal_position = po.fiscal_position or False
+        journal_obj = self.pool.get('account.journal')
+        journal_ids = journal_obj.search(cr, uid, [('type', '=','purchase'),
+            ('company_id', '=', po.company_id.id)], limit=1)
+        if not journal_ids:
+            raise osv.except_osv(
+                _('Error!'),
+                _('Define purchase journal for this company: "%s" (id:%d).') 
+                    % (po.company_id.name, 
+                        po.company_id.id))
+        return {
+            'currency_id': currency_id,
+            'partner_id': landed_cost.partner_id.id,
+            'account_id': landed_cost.partner_id.property_account_payable.id,
+            'type': 'in_invoice',
+            'origin': po.name,
+            'fiscal_position':  fiscal_position,
+            'company_id': po.company_id.id,
+            'journal_id': len(journal_ids) and journal_ids[0] or False,
+        }
+
+    def _generate_invoice_from_landed_cost(self, cr, uid, landed_cost, 
+            context=None):
+        """Generate an invoice from order landed costs (means generic 
+            costs to a whole PO) or from a line landed costs."""
+        invoice_obj = self.pool.get('account.invoice')
+        invoice_line_obj = self.pool.get('account.invoice.line')
+        prod_obj = self.pool.get('product.product')
+        po = (landed_cost.purchase_order_id or
+            landed_cost.purchase_order_line_id.order_id)
+        vals_inv = self._prepare_landed_cost_inv(cr, uid, 
+            landed_cost, context=context)
+        self._logger.debug('vals inv`%s`', vals_inv)
+        inv_id = invoice_obj.create(cr, uid, vals_inv, context=context)
+        fiscal_position = (po.fiscal_position or False)
+        exp_account_id = prod_obj._choose_exp_account_from(cr, uid,
+                landed_cost.product_id,
+                fiscal_position=fiscal_position,
+                context=context)
+        vals_line = self._prepare_landed_cost_inv_line(cr, uid,
+            exp_account_id, inv_id, landed_cost, context=context)
+        self._logger.debug('vals line `%s`', vals_line)
+        inv_line_id = invoice_line_obj.create(cr, uid, vals_line,
+            context=context)
+        return inv_id
+
+    def wkf_approve_order(self, cr, uid, ids, context=None):
+        """On PO approval, generate all invoices
+        for all landed cost position. Remember that only landed cost position with
+        the checkbox generate_invoice ticked are generated."""
+        res = super(purchase_order,self).wkf_approve_order(cr, uid, ids,
+            context=context)
+        for order in self.browse(cr, uid, ids, context=context):
+            invoice_ids = []
+            for order_cost in order.landed_cost_line_ids:
+                if order_cost.generate_invoice:
+                    inv_id = self._generate_invoice_from_landed_cost(cr, uid, 
+                        order_cost, context=context)
+                    invoice_ids.append(inv_id)
+            for po_line in order.order_line:
+                for line_cost in po_line.landed_cost_line_ids:
+                    inv_id = self._generate_invoice_from_landed_cost(cr, uid, 
+                        line_cost, context=context)
+                    invoice_ids.append(inv_id)
+            # Link this new invoice to related purchase order
+            # 4 in that list is "Add" mode in a many2many used here because
+            # the call to super() already add the main invoice
+            if invoice_ids:
+                commands = [(4, invoice_id) for invoice_id in invoice_ids]
+                order.write({'invoice_ids': commands}, context=context)
+        return res
+

=== added file 'purchase_landed_costs/purchase_view.xml'
--- purchase_landed_costs/purchase_view.xml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/purchase_view.xml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+  <data>
+
+    <record model="ir.ui.view" id="c2c_landed_cost_tree">
+      <field name="name">c2clanded.cost.tree</field>
+      <field name="model">landed.cost.position</field>
+      <field name="priority">1</field>
+      <field name="type">tree</field>
+      <field name="arch" type="xml">
+        <tree string="Landing Costs" editable="bottom">
+              <field name="generate_invoice"/>
+              <field name="product_id" context="{'landed_cost_type':'per_unit'}" on_change="onchange_product_id(product_id)"/>
+              <field name="account_id" invisible="1"/>
+              <field name="partner_id"/>
+              <field name="amount"/>
+              <field name="price_type"/>
+        </tree>
+      </field>
+    </record>
+
+     <record model="ir.ui.view" id="c2c_landed_cost_form">
+      <field name="name">c2clanded.cost.form</field>
+      <field name="model">landed.cost.position</field>
+      <field name="priority">1</field>
+      <field name="type">form</field>
+      <field name="arch" type="xml">
+        <form string="Landing Costs">
+              <field name="generate_invoice"/>
+              <field name="product_id" on_change="onchange_product_id(product_id)"/>
+              <field name="account_id" invisible="1"/>
+              <field name="partner_id"/>
+              <field name="amount"/>
+              <field name="price_type"/>
+        </form>
+      </field>
+    </record>
+    
+
+              
+        <!-- ******************
+         Landed cost definition in product form
+         ******************-->
+    <record model="ir.ui.view" id="c2c_product_landed_cost_view">
+      <field name="name">c2c_product.landed.cost.view</field>
+      <field name="model">product.product</field>
+      <field name="inherit_id" ref="product.product_normal_form_view"/>
+      <field name="type">form</field>
+      <field name="arch" type="xml">
+        <field name="description" position="before">
+           <group>
+             <field name="landed_cost_type"/>
+           </group>
+        </field>
+      </field>
+    </record>
+
+    <!-- Analysis (placed before the view due to the action in c2c_purchase_order_landed_cost_view -->
+      <record model="ir.ui.view" id="c2c_landed_cost_tree_stat">
+        <field name="name">c2clanded.cost.tree</field>
+        <field name="model">landed.cost.position</field>
+        <field name="priority">20</field>
+        <field name="type">tree</field>
+        <field name="arch" type="xml">
+          <tree string="Landing Costs" editable="bottom">
+                <field name="date_po"/>
+                <field name="product_id"/>
+                <field name="account_id" />
+                <field name="partner_id"/>
+                <field name="amount_total" sum="Total amount"/>
+                <field name="amount_total_comp_currency" sum="Total amount"/>
+                <field name="price_type"/>
+                <field name="purchase_order_id"/>
+                <field name="purchase_order_line_id"/>
+          </tree>
+        </field>
+      </record>
+
+    <record id="act_po_2_landed_costs" model="ir.actions.act_window">
+        <field name="name">Related Landed Costs</field>
+        <field name="res_model">landed.cost.position</field>
+        <field name="view_type">form</field>
+        <field name="view_mode">tree,form</field>
+        <field name="context">{'search_default_purchase_order_id': active_id}</field>          
+        <field name="view_id" ref="c2c_landed_cost_tree_stat"></field>
+    </record>
+
+    <!-- Landed costs Purchase Form-->
+    <record model="ir.ui.view" id="c2c_purchase_order_landed_cost_view">
+      <field name="name">c2c_purchase.order.landed.cost.form.view</field>
+      <field name="model">purchase.order</field>
+      <field name="inherit_id" ref="purchase.purchase_order_form"/>
+      <field name="arch" type="xml">
+       <data>
+             <field name="price_subtotal" position="after">
+                <field name="landing_costs" invisible="1"/>
+                <field name="landing_costs_order"/>
+                <field name="landed_costs"/>
+            </field> 
+        <notebook position="inside">
+          <page string="Landing Costs" attrs="{'readonly':[('state','=','done')]}">
+            <group>
+              <group>
+                <field name="quantity_total"/>
+                <field name="landed_cost_base_quantity" />
+                <field name="landed_cost_base_value" />
+              </group>
+              <group> 
+                <field name="landing_cost_lines"/>
+                <field name="landed_cost"/>
+                <button name="%(act_po_2_landed_costs)d" type="action"
+                          string="Open All Landed costs"/>
+              </group>
+             </group>
+             <field name="landed_cost_line_ids" colspan="4" nolabel="1"  widget="one2many_list">
+              <tree string="Landing Costs" editable="bottom">
+                  <field name="generate_invoice"/>
+                  <field name="product_id" context="{'landed_cost_type':'per_unit'}" on_change="onchange_product_id(product_id,parent.id)"/>
+                  <field name="account_id" invisible="1"/>
+                  <field name="partner_id"/>
+                  <field name="amount"/>
+                  <field name="price_type"/>
+              </tree>
+            </field>
+          </page>
+        </notebook>
+        </data>
+      </field>
+    </record>
+
+     <!-- inherited view to make the order lines list in the form non-editable-->
+      <record id="view_order_form_editable_list" model="ir.ui.view">
+          <field name="name">purchase.order.landed.cost.form.view.form</field>
+          <field name="model">purchase.order</field>
+          <field name="inherit_id" ref="purchase.purchase_order_form"/>
+          <field name="arch" type="xml">
+              <xpath expr="//field[@name='order_line']/tree" position="attributes">
+                  <attribute name="editable"/>
+              </xpath>
+          </field>
+      </record>   
+        
+    <!-- Landed costs Purchase Line Form-->
+    <record model="ir.ui.view" id="purchase_oder_line_landed_cost_view">
+      <field name="name">purchase.oder.line.landed.cost.view</field>
+      <field name="model">purchase.order.line</field>
+      <field name="inherit_id" ref="purchase.purchase_order_line_form"/>
+      <field name="type">form</field>
+      <field name="arch" type="xml">
+        <notebook position="inside">
+             <page string="Landing Costs" >
+                <group colspan="2" col="2"> 
+                  <field name="landing_costs"/>
+                  <field name="landing_costs_order"/>
+                  <field name="landed_costs"/>
+                  <field name="landed_cost_line_ids" colspan="4" nolabel="1"  widget="one2many_list"/>
+                </group>  
+             </page>     
+        </notebook>
+      </field>
+    </record>
+
+    <record id="view_landed_cost_search" model="ir.ui.view">
+        <field name="name">landed.cost.position.search</field>
+        <field name="model">landed.cost.position</field>
+        <field name="arch" type="xml">
+            <search string="Purchase Orders">
+                <field name="date_po"/>
+                <field name="partner_id"/>
+                <field name="account_id"/>
+                <field name="product_id"/>
+                <field name="price_type"/>
+                <field name="purchase_order_id"/>
+                <field name="purchase_order_line_id"/>
+                <newline/>
+                <group expand="1" string="Group By...">
+                    <filter string="Date" name="group_date_po" icon="terp-personal" context="{'group_by':'date_po'}"/>
+                    <filter string="Supplier" name="group_partner_id" icon="terp-personal" context="{'group_by':'partner_id'}"/>
+                    <filter string="Account" name="group_account_id" icon="terp-stock_symbol-selection" context="{'group_by':'account_id'}"/>
+                    <filter string="Landed Cost Name" name="group_product_id" icon="terp-accessories-archiver" context="{'group_by':'product_id'}"/>
+                    <filter string="Purchase" icon="terp-stock_effects-object-colorize" context="{'group_by':'purchase_order_id'}"/>
+                    <filter string="Purchase Line" icon="terp-stock_effects-object-colorize" context="{'group_by':'purchase_order_line_id'}"/>
+                </group>
+            </search>
+        </field>
+    </record>
+
+    <record model="ir.ui.view" id="landed_cost_position_graph">
+        <field name="name">landed.cost.position.graph</field>
+        <field name="model">landed.cost.position</field>
+        <field name="type">graph</field>
+        <field name="arch" type="xml">
+            <graph string="Landed Costs" type="bar">
+                <field name="account_id"/>
+                <field name="amount_total_comp_currency" operator="+"/>
+            </graph>
+        </field>
+    </record>
+
+    <record id="action_landed_cost_report_all" model="ir.actions.act_window">
+        <field name="name">Landed Costs Analysis</field>
+        <field name="res_model">landed.cost.position</field>
+        <field name="view_type">form</field>
+        <field name="view_mode">tree,graph</field>
+        <field name="view_id" ref="c2c_landed_cost_tree_stat"></field>
+        <field name="context">{'search_default_group_account_id':1,'search_default_group_product_id': 1,'group_by':[]}</field>
+        <field name="help">Landed cost Analysis allows you to easily check and analyse your estimated landed costs.</field>
+    </record>
+    <menuitem action="action_landed_cost_report_all" id="menu_action_landed_cost_report_all" parent="base.next_id_73" sequence="3"/>
+
+
+  </data>
+</openerp>

=== added directory 'purchase_landed_costs/security'
=== added file 'purchase_landed_costs/security/ir.model.access.csv'
--- purchase_landed_costs/security/ir.model.access.csv	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/security/ir.model.access.csv	2013-10-10 19:03:35 +0000
@@ -0,0 +1,3 @@
+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
+access_landed_cost,landed.cost.position,model_landed_cost_position,purchase.group_purchase_user,1,1,1,1
+access_landed_cost_manager,landed.cost.position,model_landed_cost_position,purchase.group_purchase_manager,1,1,1,1

=== added file 'purchase_landed_costs/security/landed_cost_security.xml'
--- purchase_landed_costs/security/landed_cost_security.xml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/security/landed_cost_security.xml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+
+<data noupdate="1">
+    <record id="landed_costs_comp_rule" model="ir.rule">
+        <field name="name">Landed Costs</field>
+        <field name="model_id" ref="model_landed_cost_position"/>
+        <field name="global" eval="True"/>
+        <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
+    </record>
+</data>
+
+</openerp>

=== added file 'purchase_landed_costs/stock.py'
--- purchase_landed_costs/stock.py	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/stock.py	2013-10-10 19:03:35 +0000
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2010-2013 Camptocamp (<http://www.camptocamp.com>)
+#    Authors: Ferdinand Gasauer, Joel Grand-Guillaume
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+import logging
+
+
+class stock_move(orm.Model):
+    _inherit = "stock.move"
+
+    _columns = {
+         'price_unit_net' : fields.float(
+            'Purchase Price',
+            digits_compute=dp.get_precision('Account'),
+            help="This is the net purchase price, without landed cost "
+                  "as the price include landed price has been stored in "
+                  "price_unit field"),
+    }
+
+
+class stock_partial_picking(orm.TransientModel):
+    _inherit = "stock.partial.picking"
+    _logger = logging.getLogger(__name__)
+
+    def _product_cost_for_average_update(self, cr, uid, move):
+        # Be aware of an OpenERP Bug !! If your price_type
+        # IS NOT in your comapny currency, AVG price is wrong.
+        # Currently, the cost on the product form is supposed to be expressed
+        # in the currency of the company owning the product. OpenERP 
+        # read the average price from price_get method, which 
+        # convert the price to company currency. 
+        # So, in case you have:
+        #   Rate from CHF to EUR 1.2
+        #   Company in CHF
+        #   Price type in EUR
+        #   Product AVG price = 10.-
+        #   Reception new product with cost 15.- (in CHF in price_unit 
+        #   of moves)
+        #   The price_get will return the current average price in CHF of 12.- 
+        #   The price computed will be =(12 * qty + 15 * qty') / (qty + qty')
+        #   in CHF. The new cost will be store as is in the procuct 
+        #   standard_price instead of converting the result in EUR
+        res = super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move)
+        self._logger.debug('res stock_partial_picking `%s`', res)
+        # Re-take the cost from the PO line landed_costs field
+        res['cost'] = move.purchase_line_id.landed_costs / move.purchase_line_id.product_qty
+        self._logger.debug('res stock_partial_picking `%s`', res)
+        return res

=== added directory 'purchase_landed_costs/test'
=== added file 'purchase_landed_costs/test/landed_costs_based_on_quantity.yml'
--- purchase_landed_costs/test/landed_costs_based_on_quantity.yml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/test/landed_costs_based_on_quantity.yml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,147 @@
+-
+  Ensure main company, price_type of standard_price and pricelist are in EUR
+-
+ !record {model: res.company, id: base.main_company}:
+    currency_id: base.EUR
+-
+ !record {model: product.price.type, id: product.standard_price}:
+    currency_id: base.EUR
+-
+ !record {model: product.pricelist, id: purchase.list0}:
+    currency_id: base.EUR 
+-
+  Affect the admin user to the main company
+-
+ !record {model: res.users, id: base.user_root}:
+    company_id: base.main_company 
+-
+  Create a stock location for the test
+-
+ !record {model: stock.location, id: location_stock_01}:
+    name: Stock for PO
+    usage: internal
+-
+  Create a Supplier for PO
+-
+  !record {model: res.partner, id: res_partner_supplier_01}:
+    name: Supplier 1
+    supplier: 1
+-
+  Create a Supplier for landed cost
+-
+  !record {model: res.partner, id: res_partner_supplier_02}:
+    name: Supplier 2
+    supplier: 1
+-
+  Create a product with landed type Quantity
+-
+  !record {model: product.product, id: product_product_lcost_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    landed_cost_type: per_unit
+    name: Transport Poste Express Quantity
+    standard_price: 50.0
+    list_price: 75.0
+    type: service
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+    volume: 0.0
+    warranty: 0.0
+    weight: 0.0
+    weight_net: 0.0
+-
+  Create a wine product A with an avg price of 100
+-
+  !record {model: product.product, id: product_product_a_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine A
+    standard_price: 100.0
+    list_price: 150.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a wine product B with an avg price of 200
+-
+  !record {model: product.product, id: product_product_b_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine B
+    standard_price: 200.0
+    list_price: 250.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a purchase order with two lines and one landed cost based on quantity
+-
+  !record {model: purchase.order, id: purchase_order_lcost_01}:
+    partner_id: res_partner_supplier_01
+    invoice_method: order
+    location_id: location_stock_01
+    pricelist_id: purchase.list0
+    order_line:
+      - product_id: product_product_a_avg_01
+        price_unit: 100
+        product_qty: 15.0
+      - product_id: product_product_b_avg_01
+        price_unit: 200
+        product_qty: 5.0
+    landed_cost_line_ids:
+      - product_id: product_product_lcost_01
+        amount: 50
+        partner_id: res_partner_supplier_02
+        generate_invoice: 1
+        price_type: per_unit
+-
+  Test the landed costs computation by lines
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_01'))
+    for line in po.order_line:
+      # Compute pro-rata of quantity for line
+      value = (line.product_qty / (15+5)) * 50
+      assert line.landing_costs_order == value, "The landing cost based on quantity has not been computed correctly"
+-
+ I confirm the order where invoice control is 'Bases on order'.
+-
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lcost_01}
+-
+  I check that the landed cost invoice and PO one is generated from PO confirmation
+-
+  !python {model: purchase.order}: |
+    purchase_order = self.browse(cr, uid, ref("purchase_order_lcost_01"))
+    assert len(purchase_order.invoice_ids) == 2, "2 invoices (PO + landed cost) should have been generated on order confirmation."
+-
+  Reception is ready for process, make it and check moves value
+-
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lcost_01")).picking_ids
+    partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+    picking = self.pool.get('stock.picking').browse(cr, uid, [pick_ids[0].id])[0]
+    for move in picking.move_lines:
+      if move.product_id.name == 'Wine A':
+        assert move.price_unit == 102.5,"Technical field price_unit of Wine A stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 100.0,"Technical field price_unit of Wine A stock move should record the purchase price"
+      elif move.product_id.name == 'Wine B':
+        assert move.price_unit == 202.5,"Technical field price_unit of Wine B stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 200.0,"Technical field price_unit_net of Wine B stock move should record the purchase price"
+-
+  I check that purchase order is shipped.
+-
+  !python {model: purchase.order}: |
+     assert self.browse(cr, uid, ref("purchase_order_lcost_01")).shipped == True,"Purchase order should be delivered"
+-
+  I check that avg price of products is computed with landed costs
+-
+  !python {model: product.product}: |
+     # computed as : ((15/20) * 50 + 100 * 15) / 15
+     value_a = 102.5
+     # computed as : ((5/20) * 50 + 200 * 5) / 5
+     value_b = 202.5
+     assert self.browse(cr, uid, ref("product_product_a_avg_01")).standard_price == value_a,"Avg price for product Wine A is wrongly computed"
+     assert self.browse(cr, uid, ref("product_product_b_avg_01")).standard_price == value_b,"Avg price for product Wine B is wrongly computed"

=== added file 'purchase_landed_costs/test/landed_costs_based_on_value.yml'
--- purchase_landed_costs/test/landed_costs_based_on_value.yml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/test/landed_costs_based_on_value.yml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,141 @@
+-
+  Ensure main company, price_type of standard_price and pricelist are in EUR
+-
+ !record {model: res.company, id: base.main_company}:
+    currency_id: base.EUR
+-
+ !record {model: product.price.type, id: product.standard_price}:
+    currency_id: base.EUR
+-
+ !record {model: product.pricelist, id: purchase.list0}:
+    currency_id: base.EUR 
+-
+  Affect the admin user to the main company
+-
+ !record {model: res.users, id: base.user_root}:
+    company_id: base.main_company 
+-
+  Create a Supplier for PO
+-
+  !record {model: res.partner, id: res_partner_supplier_03}:
+    name: Supplier 3
+    supplier: 1
+-
+  Create a Supplier for landed cost
+-
+  !record {model: res.partner, id: res_partner_supplier_04}:
+    name: Supplier 4
+    supplier: 1
+-
+  Create a product with landed type value
+-
+  !record {model: product.product, id: product_product_lcost_02}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    landed_cost_type: value
+    name: Transport Poste Express Value
+    standard_price: 50.0
+    list_price: 75.0
+    type: service
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+    volume: 0.0
+    warranty: 0.0
+    weight: 0.0
+    weight_net: 0.0
+-
+  Create a wine product C with an avg price of 100
+-
+  !record {model: product.product, id: product_product_c_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine C
+    standard_price: 100.0
+    list_price: 150.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a wine product D with an avg price of 200
+-
+  !record {model: product.product, id: product_product_d_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine D
+    standard_price: 200.0
+    list_price: 250.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a purchase order with two lines and one landed cost based on value
+-
+  !record {model: purchase.order, id: purchase_order_lcost_02}:
+    partner_id: res_partner_supplier_03
+    invoice_method: order
+    location_id: location_stock_01
+    pricelist_id: purchase.list0
+    order_line:
+      - product_id: product_product_c_avg_01
+        price_unit: 100
+        product_qty: 15.0
+      - product_id: product_product_d_avg_01
+        price_unit: 200
+        product_qty: 5.0
+    landed_cost_line_ids:
+      - product_id: product_product_lcost_02
+        amount: 50
+        partner_id: res_partner_supplier_04
+        generate_invoice: 1
+        price_type: value
+-
+  Test the landed costs computation by lines
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_02'))
+    for line in po.order_line:
+      # Compute pro-rata of value for line
+      value = (line.price_subtotal / (15 * 100 + 5 * 200)) * 50
+      assert line.landing_costs_order == value, "The landing cost based on value has not been computed correctly"
+-
+  I confirm the order where invoice control is 'Bases on order'.
+-
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lcost_02}
+-
+  I check that the landed cost invoice and PO one is generated from PO confirmation
+-
+  !python {model: purchase.order}: |
+    purchase_order = self.browse(cr, uid, ref("purchase_order_lcost_02"))
+    assert len(purchase_order.invoice_ids) == 2, "2 invoices (PO + landed cost) should have been generated on order confirmation."
+-
+  Reception is ready for process, make it and check moves value
+-
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lcost_02")).picking_ids
+    partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+    picking = self.pool.get('stock.picking').browse(cr, uid, [pick_ids[0].id])[0]
+    for move in picking.move_lines:
+      if move.product_id.name == 'Wine C':
+        assert move.price_unit == 102.0,"Technical field price_unit of Wine C stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 100.0,"Technical field price_unit of Wine C stock move should record the purchase price"
+      elif move.product_id.name == 'Wine D':
+        assert move.price_unit == 204.0,"Technical field price_unit of Wine D stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 200.0,"Technical field price_unit_net of Wine D stock move should record the purchase price"
+-
+  I check that purchase order is shipped.
+-
+  !python {model: purchase.order}: |
+     assert self.browse(cr, uid, ref("purchase_order_lcost_02")).shipped == True,"Purchase order should be delivered"
+-
+  I check that avg price of products is computed with landed costs
+-
+  !python {model: product.product}: |
+     # computed as : ((15/20) * 50 + 100 * 15) / 15
+     value_c = 102.0
+     # computed as : ((5/20) * 50 + 200 * 5) / 5
+     value_d = 204.0
+     assert self.browse(cr, uid, ref("product_product_c_avg_01")).standard_price == value_c,"Avg price for product Wine A is wrongly computed"
+     assert self.browse(cr, uid, ref("product_product_d_avg_01")).standard_price == value_d,"Avg price for product Wine B is wrongly computed"

=== added file 'purchase_landed_costs/test/landed_costs_multicurrency_company.yml'
--- purchase_landed_costs/test/landed_costs_multicurrency_company.yml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/test/landed_costs_multicurrency_company.yml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,159 @@
+-
+  Setup the Company as CHF (rate 1.3086) while keeping pricelist and price_type as EUR
+-
+ !record {model: res.currency.rate, id: base.rateCHF}:
+    rate: 1.3086
+    currency_id: base.CHF
+    name: !eval time.strftime('%Y-01-01')
+-
+ !record {model: res.currency.rate, id: base.rateEUR}:
+    rate: 1.0
+    currency_id: base.EUR
+    name: !eval time.strftime('%Y-01-01')
+-
+ !record {model: res.company, id: base.main_company}:
+    currency_id: base.CHF
+-
+ !record {model: product.price.type, id: product.standard_price}:
+    currency_id: base.EUR
+-
+ !record {model: product.pricelist, id: purchase.list0}:
+    currency_id: base.EUR 
+-
+  Affect the admin user to the main company
+-
+ !record {model: res.users, id: base.user_root}:
+    company_id: base.main_company 
+-
+  Create a stock location for the test
+-
+ !record {model: stock.location, id: location_stock_01}:
+    name: Stock for PO
+    usage: internal
+-
+  Create a Supplier for PO
+-
+  !record {model: res.partner, id: res_partner_supplier_01}:
+    name: Supplier 1
+    supplier: 1
+-
+  Create a Supplier for landed cost
+-
+  !record {model: res.partner, id: res_partner_supplier_02}:
+    name: Supplier 2
+    supplier: 1
+-
+  Create a product with landed type Quantity
+-
+  !record {model: product.product, id: product_product_lcost_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    landed_cost_type: per_unit
+    name: Transport Poste Express Quantity
+    standard_price: 50.0
+    list_price: 75.0
+    type: service
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+    volume: 0.0
+    warranty: 0.0
+    weight: 0.0
+    weight_net: 0.0
+-
+  Create a wine product H with an avg price of 100
+-
+  !record {model: product.product, id: product_product_h_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine H
+    standard_price: 100.0
+    list_price: 150.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a wine product I with an avg price of 200
+-
+  !record {model: product.product, id: product_product_i_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine I
+    standard_price: 200.0
+    list_price: 250.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a purchase order with two lines and one landed cost based on quantity
+-
+  !record {model: purchase.order, id: purchase_order_lcost_05}:
+    partner_id: res_partner_supplier_01
+    invoice_method: order
+    location_id: location_stock_01
+    pricelist_id: purchase.list0
+    order_line:
+      - product_id: product_product_h_avg_01
+        price_unit: 100
+        product_qty: 15.0
+      - product_id: product_product_i_avg_01
+        price_unit: 200
+        product_qty: 5.0
+    landed_cost_line_ids:
+      - product_id: product_product_lcost_01
+        amount: 50
+        partner_id: res_partner_supplier_02
+        generate_invoice: 1
+        price_type: per_unit
+-
+  Test the landed costs computation by lines
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_05'))
+    for line in po.order_line:
+      # Compute pro-rata of quantity for line
+      value = (line.product_qty / (15+5)) * 50
+      assert line.landing_costs_order == value, "The landing cost based on quantity has not been computed correctly"
+-
+ I confirm the order where invoice control is 'Bases on order'.
+-
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lcost_05}
+-
+  I check that the landed cost invoice and PO one is generated from PO confirmation
+-
+  !python {model: purchase.order}: |
+    purchase_order = self.browse(cr, uid, ref("purchase_order_lcost_05"))
+    assert len(purchase_order.invoice_ids) == 2, "2 invoices (PO + landed cost) should have been generated on order confirmation."
+-
+  Reception is ready for process, make it and check moves value
+-
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lcost_05")).picking_ids
+    partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+    picking = self.pool.get('stock.picking').browse(cr, uid, [pick_ids[0].id])[0]
+    for move in picking.move_lines:
+      if move.product_id.name == 'Wine H':
+        assert move.price_unit == 102.5,"Technical field price_unit of Wine H stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 100.0,"Technical field price_unit of Wine H stock move should record the purchase price"
+      elif move.product_id.name == 'Wine I':
+        assert move.price_unit == 202.5,"Technical field price_unit of Wine I stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 200.0,"Technical field price_unit_net of Wine I stock move should record the purchase price"
+-
+  I check that purchase order is shipped.
+-
+  !python {model: purchase.order}: |
+     assert self.browse(cr, uid, ref("purchase_order_lcost_05")).shipped == True,"Purchase order should be delivered"
+-
+  I check that avg price of products is computed with landed costs
+-
+  !python {model: product.product}: |
+     # computed as : ((15/20) * 50 + 100 * 15) / 15
+     value_a = 102.5
+     # computed as : ((5/20) * 50 + 200 * 5) / 5
+     value_b = 202.5
+     print self.browse(cr, uid, ref("product_product_h_avg_01")).standard_price
+     print self.browse(cr, uid, ref("product_product_i_avg_01")).standard_price
+     assert self.browse(cr, uid, ref("product_product_h_avg_01")).standard_price == value_a,"Avg price for product Wine H is wrongly computed"
+     assert self.browse(cr, uid, ref("product_product_i_avg_01")).standard_price == value_b,"Avg price for product Wine I is wrongly computed"

=== added file 'purchase_landed_costs/test/landed_costs_multicurrency_pricelist.yml'
--- purchase_landed_costs/test/landed_costs_multicurrency_pricelist.yml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/test/landed_costs_multicurrency_pricelist.yml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,158 @@
+-
+  Setup the pricelist as CHF (rate 1.3086) while keeping company and price_type as EUR
+-
+ !record {model: res.currency.rate, id: base.rateCHF}:
+    rate: 1.3086
+    currency_id: base.CHF
+    name: !eval time.strftime('%Y-01-01')
+-
+ !record {model: res.currency.rate, id: base.rateEUR}:
+    rate: 1.0
+    currency_id: base.EUR
+    name: !eval time.strftime('%Y-01-01')
+-
+ !record {model: res.company, id: base.main_company}:
+    currency_id: base.EUR
+-
+ !record {model: product.price.type, id: product.standard_price}:
+    currency_id: base.EUR
+-
+ !record {model: product.pricelist, id: purchase.list0}:
+    currency_id: base.CHF 
+-
+  Affect the admin user to the main company
+-
+ !record {model: res.users, id: base.user_root}:
+    company_id: base.main_company 
+-
+  Create a stock location for the test
+-
+ !record {model: stock.location, id: location_stock_01}:
+    name: Stock for PO
+    usage: internal
+-
+  Create a Supplier for PO
+-
+  !record {model: res.partner, id: res_partner_supplier_01}:
+    name: Supplier 1
+    supplier: 1
+-
+  Create a Supplier for landed cost
+-
+  !record {model: res.partner, id: res_partner_supplier_02}:
+    name: Supplier 2
+    supplier: 1
+-
+  Create a product with landed type Quantity
+-
+  !record {model: product.product, id: product_product_lcost_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    landed_cost_type: per_unit
+    name: Transport Poste Express Quantity
+    standard_price: 50.0
+    list_price: 75.0
+    type: service
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+    volume: 0.0
+    warranty: 0.0
+    weight: 0.0
+    weight_net: 0.0
+-
+  Create a wine product F with an avg price of 100
+-
+  !record {model: product.product, id: product_product_f_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine F
+    standard_price: 100.0
+    list_price: 150.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a wine product G with an avg price of 200
+-
+  !record {model: product.product, id: product_product_g_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine G
+    standard_price: 200.0
+    list_price: 250.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a purchase order with two lines and one landed cost based on quantity
+-
+  !record {model: purchase.order, id: purchase_order_lcost_04}:
+    partner_id: res_partner_supplier_01
+    invoice_method: order
+    location_id: location_stock_01
+    pricelist_id: purchase.list0
+    order_line:
+      - product_id: product_product_f_avg_01
+        price_unit: 100
+        product_qty: 15.0
+      - product_id: product_product_g_avg_01
+        price_unit: 200
+        product_qty: 5.0
+    landed_cost_line_ids:
+      - product_id: product_product_lcost_01
+        amount: 50
+        partner_id: res_partner_supplier_02
+        generate_invoice: 1
+        price_type: per_unit
+-
+  Test the landed costs computation by lines
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_04'))
+    for line in po.order_line:
+      # Compute pro-rata of quantity for line
+      value = (line.product_qty / (15+5)) * 50
+      assert line.landing_costs_order == value, "The landing cost based on quantity has not been computed correctly"
+-
+ I confirm the order where invoice control is 'Bases on order'.
+-
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lcost_04}
+-
+  I check that the landed cost invoice and PO one is generated from PO confirmation
+-
+  !python {model: purchase.order}: |
+    purchase_order = self.browse(cr, uid, ref("purchase_order_lcost_04"))
+    assert len(purchase_order.invoice_ids) == 2, "2 invoices (PO + landed cost) should have been generated on order confirmation."
+-
+  Reception is ready for process, make it and check moves value
+-
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lcost_04")).picking_ids
+    partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+    picking = self.pool.get('stock.picking').browse(cr, uid, [pick_ids[0].id])[0]
+    for move in picking.move_lines:
+      if move.product_id.name == 'Wine A':
+        assert move.price_unit == 102.5,"Technical field price_unit of Wine F stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 100.0,"Technical field price_unit of Wine F stock move should record the purchase price"
+      elif move.product_id.name == 'Wine B':
+        assert move.price_unit == 202.5,"Technical field price_unit of Wine G stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 200.0,"Technical field price_unit_net of Wine G stock move should record the purchase price"
+-
+  I check that purchase order is shipped.
+-
+  !python {model: purchase.order}: |
+     assert self.browse(cr, uid, ref("purchase_order_lcost_04")).shipped == True,"Purchase order should be delivered"
+-
+  I check that avg price of products is computed with landed costs
+-
+  !python {model: product.product}: |
+     xchg_rate_chf = 1.3086
+     # computed as : ((15/20) * 50 + 100 * 15) / 15
+     value_a = round(102.5 / xchg_rate_chf, 2)
+     # computed as : ((5/20) * 50 + 200 * 5) / 5
+     value_b = round(202.5 / xchg_rate_chf, 2)
+     assert self.browse(cr, uid, ref("product_product_f_avg_01")).standard_price == value_a,"Avg price for product Wine F is wrongly computed"
+     assert self.browse(cr, uid, ref("product_product_g_avg_01")).standard_price == value_b,"Avg price for product Wine G is wrongly computed"

=== added file 'purchase_landed_costs/test/landed_costs_multicurrency_pricetype.yml'
--- purchase_landed_costs/test/landed_costs_multicurrency_pricetype.yml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/test/landed_costs_multicurrency_pricetype.yml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,160 @@
+-
+  Setup the Company as CHF (rate 1.3086) while keeping pricelist and price_type as EUR
+-
+ !record {model: res.currency.rate, id: base.rateCHF}:
+    rate: 1.3086
+    currency_id: base.CHF
+    name: !eval time.strftime('%Y-01-01')
+-
+ !record {model: res.currency.rate, id: base.rateEUR}:
+    rate: 1.0
+    currency_id: base.EUR
+    name: !eval time.strftime('%Y-01-01')
+-
+ !record {model: res.company, id: base.main_company}:
+    currency_id: base.EUR
+-
+ !record {model: product.price.type, id: product.standard_price}:
+    currency_id: base.CHF
+-
+ !record {model: product.pricelist, id: purchase.list0}:
+    currency_id: base.EUR 
+-
+  Affect the admin user to the main company
+-
+ !record {model: res.users, id: base.user_root}:
+    company_id: base.main_company 
+-
+  Create a stock location for the test
+-
+ !record {model: stock.location, id: location_stock_01}:
+    name: Stock for PO
+    usage: internal
+-
+  Create a Supplier for PO
+-
+  !record {model: res.partner, id: res_partner_supplier_01}:
+    name: Supplier 1
+    supplier: 1
+-
+  Create a Supplier for landed cost
+-
+  !record {model: res.partner, id: res_partner_supplier_02}:
+    name: Supplier 2
+    supplier: 1
+-
+  Create a product with landed type Quantity
+-
+  !record {model: product.product, id: product_product_lcost_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    landed_cost_type: per_unit
+    name: Transport Poste Express Quantity
+    standard_price: 50.0
+    list_price: 75.0
+    type: service
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+    volume: 0.0
+    warranty: 0.0
+    weight: 0.0
+    weight_net: 0.0
+-
+  Create a wine product J with an avg price of 100
+-
+  !record {model: product.product, id: product_product_j_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine J
+    standard_price: 100.0
+    list_price: 150.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a wine product K with an avg price of 200
+-
+  !record {model: product.product, id: product_product_k_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine K
+    standard_price: 200.0
+    list_price: 250.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a purchase order with two lines and one landed cost based on quantity
+-
+  !record {model: purchase.order, id: purchase_order_lcost_06}:
+    partner_id: res_partner_supplier_01
+    invoice_method: order
+    location_id: location_stock_01
+    pricelist_id: purchase.list0
+    order_line:
+      - product_id: product_product_j_avg_01
+        price_unit: 100
+        product_qty: 15.0
+      - product_id: product_product_k_avg_01
+        price_unit: 200
+        product_qty: 5.0
+    landed_cost_line_ids:
+      - product_id: product_product_lcost_01
+        amount: 50
+        partner_id: res_partner_supplier_02
+        generate_invoice: 1
+        price_type: per_unit
+-
+  Test the landed costs computation by lines
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_06'))
+    for line in po.order_line:
+      # Compute pro-rata of quantity for line
+      value = (line.product_qty / (15+5)) * 50
+      assert line.landing_costs_order == value, "The landing cost based on quantity has not been computed correctly"
+-
+ I confirm the order where invoice control is 'Bases on order'.
+-
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lcost_06}
+-
+  I check that the landed cost invoice and PO one is generated from PO confirmation
+-
+  !python {model: purchase.order}: |
+    purchase_order = self.browse(cr, uid, ref("purchase_order_lcost_06"))
+    assert len(purchase_order.invoice_ids) == 2, "2 invoices (PO + landed cost) should have been generated on order confirmation."
+-
+  Reception is ready for process, make it and check moves value
+-
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lcost_06")).picking_ids
+    partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+    picking = self.pool.get('stock.picking').browse(cr, uid, [pick_ids[0].id])[0]
+    for move in picking.move_lines:
+      if move.product_id.name == 'Wine J':
+        assert move.price_unit == 102.5,"Technical field price_unit of Wine J stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 100.0,"Technical field price_unit of Wine J stock move should record the purchase price"
+      elif move.product_id.name == 'Wine K':
+        assert move.price_unit == 202.5,"Technical field price_unit of Wine K stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 200.0,"Technical field price_unit_net of Wine K stock move should record the purchase price"
+-
+  I check that purchase order is shipped.
+-
+  !python {model: purchase.order}: |
+     assert self.browse(cr, uid, ref("purchase_order_lcost_06")).shipped == True,"Purchase order should be delivered"
+-
+  I check that avg price of products is computed with landed costs
+-
+  !python {model: product.product}: |
+     xchg_rate_chf = 1.3086
+     # computed as : ((15/20) * 50 + 100 * 15) / 15
+     value_a = round(102.5 * xchg_rate_chf, 2)
+     # computed as : ((5/20) * 50 + 200 * 5) / 5
+     value_b = round(202.5 * xchg_rate_chf, 2)
+     print self.browse(cr, uid, ref("product_product_j_avg_01")).standard_price
+     print self.browse(cr, uid, ref("product_product_k_avg_01")).standard_price
+     assert self.browse(cr, uid, ref("product_product_j_avg_01")).standard_price == value_a,"Avg price for product Wine J is wrongly computed"
+     assert self.browse(cr, uid, ref("product_product_k_avg_01")).standard_price == value_b,"Avg price for product Wine K is wrongly computed"

=== added file 'purchase_landed_costs/test/landed_costs_on_qty_by_line_and_order.yml'
--- purchase_landed_costs/test/landed_costs_on_qty_by_line_and_order.yml	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/test/landed_costs_on_qty_by_line_and_order.yml	2013-10-10 19:03:35 +0000
@@ -0,0 +1,144 @@
+-
+  Ensure main company, price_type of standard_price and pricelist are in EUR
+-
+ !record {model: res.company, id: base.main_company}:
+    currency_id: base.EUR
+-
+ !record {model: product.price.type, id: product.standard_price}:
+    currency_id: base.EUR
+-
+ !record {model: product.pricelist, id: purchase.list0}:
+    currency_id: base.EUR 
+-
+  Affect the admin user to the main company
+-
+ !record {model: res.users, id: base.user_root}:
+    company_id: base.main_company 
+-
+  Create a product with landed type for lines
+-
+  !record {model: product.product, id: product_product_lcost_03}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    landed_cost_type: per_unit
+    name: Line fees
+    standard_price: 20.0
+    list_price: 20.0
+    type: service
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+    volume: 0.0
+    warranty: 0.0
+    weight: 0.0
+    weight_net: 0.0
+-
+  Create a wine product E with an avg price of 100
+-
+  !record {model: product.product, id: product_product_e_avg_01}:
+    categ_id: product.product_category_1
+    cost_method: standard
+    name: Wine E
+    standard_price: 100.0
+    list_price: 150.0
+    type: product
+    cost_method: average
+    uom_id: product.product_uom_unit
+    uom_po_id: product.product_uom_unit
+-
+  Create a purchase order with two lines and one landed cost based on quantity
+  And one landed cost for the first line
+-
+  !record {model: purchase.order, id: purchase_order_lcost_03}:
+    partner_id: res_partner_supplier_01
+    invoice_method: order
+    location_id: location_stock_01
+    pricelist_id: purchase.list0
+    order_line:
+      - product_id: product_product_e_avg_01
+        price_unit: 100
+        product_qty: 15.0
+        landed_cost_line_ids:
+          - product_id: product_product_lcost_03
+            amount: 20
+            partner_id: res_partner_supplier_02
+            generate_invoice: 1
+            price_type: per_unit
+      - product_id: product_product_b_avg_01
+        price_unit: 200
+        product_qty: 5.0
+    landed_cost_line_ids:
+      - product_id: product_product_lcost_01
+        amount: 50
+        partner_id: res_partner_supplier_02
+        generate_invoice: 1
+        price_type: per_unit
+-
+  Test the landed costs computation for whole order
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_03'))
+    for line in po.order_line:
+      # Compute pro-rata of quantity for line
+      value = (line.product_qty / (15+5)) * 50
+      assert line.landing_costs_order == value, "The landing cost based on quantity has not been computed correctly"
+-
+  Test the landed costs computation of the lines
+-
+  !python {model: purchase.order}: |
+    po = self.browse(cr, uid, ref('purchase_order_lcost_03'))
+    for line in po.order_line:
+      if line.product_id.name == 'Wine E':
+        # Value for the first line should be equal to landed cost of the line * qty
+        value_landing = 20 * line.product_qty
+        # value is landing value + landing cost order + price_subtotal of po line
+        value_landed = value_landing + (line.product_qty / (15+5)) * 50 + line.price_subtotal
+        assert line.landing_costs == value_landing, "The landing cost of the line has not been computed correctly"
+        assert line.landed_costs == value_landed, "The landed costs of the line has not been computed correctly"
+      elif line.product_id.name == 'Wine B':
+        # Value for the first line should be equal to landed cost of the line * qty
+        value_landing = 0 * line.product_qty
+        # value is landing value + landing cost order + price_subtotal of po line
+        value_landed = value_landing + (line.product_qty / (15+5)) * 50 + line.price_subtotal
+        assert line.landing_costs == value_landing, "The landing cost of the line has not been computed correctly"
+        assert line.landed_costs == value_landed, "The landed costs of the line has not been computed correctly"
+-
+  I confirm the order where invoice control is 'Bases on order'.
+-
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lcost_03}
+-
+  I check that the landed cost invoice and PO one is generated from PO confirmation
+-
+  !python {model: purchase.order}: |
+    purchase_order = self.browse(cr, uid, ref("purchase_order_lcost_03"))
+    assert len(purchase_order.invoice_ids) == 3, "3 invoices (PO + landed cost) should have been generated on order confirmation."
+-
+  Reception is ready for process, make it and check moves value
+-
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lcost_03")).picking_ids
+    partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+    picking = self.pool.get('stock.picking').browse(cr, uid, [pick_ids[0].id])[0]
+    for move in picking.move_lines:
+      if move.product_id.name == 'Wine E':
+        assert move.price_unit == 122.5,"Technical field price_unit of Wine E stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 100.0,"Technical field price_unit of Wine E stock move should record the purchase price"
+      elif move.product_id.name == 'Wine B':
+        assert move.price_unit == 202.5,"Technical field price_unit of Wine B stock move should record the landed_costs, not purchase price"
+        assert move.price_unit_net == 200.0,"Technical field price_unit_net of Wine B stock move should record the purchase price"
+-
+  I check that purchase order is shipped.
+-
+  !python {model: purchase.order}: |
+     assert self.browse(cr, uid, ref("purchase_order_lcost_03")).shipped == True,"Purchase order should be delivered"
+-
+  I check that avg price of products is computed with landed costs
+-
+  !python {model: product.product}: |
+     # computed as : ((15/20) * 50 + 100 * 15) / 15
+     value_a = 122.5
+     # Here this scenario : landed_costs_based_on_quantity set the AVG price to 202.5; 5 PCE in stock
+     # computed as : ((5 * 202.5) + ( 5 * 202.5)) / 10
+     value_b = 202.5
+     assert self.browse(cr, uid, ref("product_product_e_avg_01")).standard_price == value_a,"Avg price for product Wine E is wrongly computed"
+     assert self.browse(cr, uid, ref("product_product_b_avg_01")).standard_price == value_b,"Avg price for product Wine B is wrongly computed"

=== added directory 'purchase_landed_costs/wizard'

Follow ups