← Back to team overview

openerp-community-reviewer team mailing list archive

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

 

Joël Grand-Guillaume @ camptocamp has proposed merging lp:~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge into lp:purchase-wkfl.

Commit message:
[ADD] the module purchase_landed_cost that bring estimated landed cost in PO into the average price computation

Requested reviews:
  Purchase Core Editors (purchase-core-editors)

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.

Thanks for review !

Regards,

Joël
-- 
https://code.launchpad.net/~camptocamp-reviewer/purchase-wkfl/purchase_landed_costs-jge/+merge/190207
Your team Purchase Core Editors 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-09 18:00:07 +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/>.     
+#
+##############################################################################
+
+
+import product
+import purchase
+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-09 18:00:07 +0000
@@ -0,0 +1,106 @@
+# -*- 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 in 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 can be defined in purchase orders. Those costs will be distributed according to the
+distribution type defined in landed cost:
+
+ * value - example custom fees
+ * quantity - example freight
+
+For each landed cost position define in a PO, a draft invoice can be created in validation of purchase
+order (an option need to be checked). Those invoice will then appear using the view invoice button of PO.
+
+The products used to define landed cost must be classified "Distribution Type" as :
+
+ * "Value" (for customs) or 
+ * "Quantity" (for freight)
+
+You can define landed cost relative to a whole PO or by 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 incomming shippment reception), you will have a little difference between
+accounting and stock valuation that will need to be corrected when making the stock accounting entry. 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 acces 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. e.g.
+    - 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.
+
+TODO/Ideas:
+-----------
+ * Manage multi-currencies in landed costs
+ * 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',
+    ],
+    '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/de.po'
--- purchase_landed_costs/i18n/de.po	1970-01-01 00:00:00 +0000
+++ purchase_landed_costs/i18n/de.po	2013-10-09 18:00:07 +0000
@@ -0,0 +1,333 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# 	* purchase_landed_costs
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 6.1rc1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-02-12 08:57+0000\n"
+"PO-Revision-Date: 2012-02-13 09:37+0000\n"
+"Last-Translator: Ferdinand @ Camptocamp <Unknown>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-23 05:13+0000\n"
+"X-Generator: Launchpad (build 16179)\n"
+
+#. module: purchase_landed_costs
+#: field:product.category,landed_cost:0 field:product.template,landed_cost:0
+msgid "Calculate Landed Costs"
+msgstr "Berechnete Einstandskosten"
+
+#. module: purchase_landed_costs
+#: sql_constraint:purchase.order:0
+msgid "Order Reference must be unique per Company!"
+msgstr "Bestellbezug muss je Unternehmen eindeutig sein!"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_purchase_order_line
+#: field:landed.cost.position,purchase_order_line_id:0
+msgid "Purchase Order Line"
+msgstr "Einkaufspositionen"
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,move_line_id:0
+msgid "Picking Line"
+msgstr "Lieferscheinzeile"
+
+#. module: purchase_landed_costs
+#: field:stock.move,sub_total:0
+msgid "Line Sub Total"
+msgstr "Zeile Teilsumme"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,partner_id:0
+msgid "The supplier of this cost component ."
+msgstr "Der Lieferant dieser Kostenkomponente"
+
+#. module: purchase_landed_costs
+#: constraint:product.template:0
+msgid ""
+"Error: The default UOM and the purchase UOM must be in the same category."
+msgstr ""
+"Fehler: Die Standard Mengeneinheit (ME) sowie die Mengeneinheit (ME) bei der "
+"Beschaffung muss in derselben Kategorie sein."
+
+#. module: purchase_landed_costs
+#: constraint:stock.move:0
+msgid "You must assign a production lot for this product"
+msgstr "Sie müssen zwingend eine Losnummer für dieses Produkt angeben"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,amount_currency:0
+msgid "The amount expressed in an optional other currency."
+msgstr "optionaler Betrag in anderer Währung"
+
+#. 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 ""
+"Aktivieren, wenn dieses Produkt als Bestellnebenkosten für die "
+"Durschnittspreisberechung verfügbar sein soll. Wenn die Nebenkosten für den "
+"Lieferschein definiert sind, gibt dies an, welcher Schüssel (Mengen, Wert) "
+"für die Verteilung verwendet werden soll."
+
+#. module: purchase_landed_costs
+#: selection:landed.cost.position,price_type:0
+msgid "Per Unit"
+msgstr "Je Einheit"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_picking
+msgid "Picking List"
+msgstr "Lieferschein"
+
+#. 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
+#: field:stock.move,landing_costs_picking:0
+msgid "Landing Costs from Picking"
+msgstr "Einstandsnebenkosten vom Lieferschien"
+
+#. module: purchase_landed_costs
+#: selection:landed.cost.position,price_type:0
+msgid "Absolute Value"
+msgstr "Absoluter Wert"
+
+#. module: purchase_landed_costs
+#: help:product.template,landed_cost:0
+msgid ""
+"Checck this if you want to use landed cost calculation for average price for "
+"this product"
+msgstr ""
+
+#. module: purchase_landed_costs
+#: field:purchase.order,landed_cost_line_ids:0
+#: field:purchase.order.line,landed_costs:0 field:stock.move,landed_cost:0
+msgid "Landed Costs"
+msgstr "Einstandskosten"
+
+#. module: purchase_landed_costs
+#: constraint:stock.move:0
+msgid "You try to assign a lot which is not from the same product"
+msgstr ""
+"Sie versuchen eine Losnummer ohne Bezug zu diesem Produkt zuzuweisen."
+
+#. module: purchase_landed_costs
+#: constraint:stock.move:0
+msgid "You can not move products from or to a location of the type view."
+msgstr "Sie können keine Buchungen auf Sichten machen"
+
+#. module: purchase_landed_costs
+#: view:landed.cost.position:0 view:purchase.order:0
+#: view:purchase.order.line:0 field:purchase.order.line,landing_costs:0
+#: view:stock.picking:0
+msgid "Landing Costs"
+msgstr "Einstandsnebenkosten"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_partial_picking_line
+msgid "stock.partial.picking.line"
+msgstr "pstock.partial.picking.line"
+
+#. module: purchase_landed_costs
+#: field:purchase.order,quantity_total:0 field:stock.picking,quantity_total:0
+msgid "Total Quantity"
+msgstr "Gesamtmenge"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,currency_id:0
+msgid "Optional other currency."
+msgstr "Optional andere Währung"
+
+#. module: purchase_landed_costs
+#: field:purchase.order,landed_cost_base_value:0
+#: field:stock.picking,landed_cost_base_value:0
+msgid "Landed Costs Base Value"
+msgstr "Einstandskosten Basis Wert"
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,picking_id:0
+msgid "Picking"
+msgstr "Lieferschein"
+
+#. module: purchase_landed_costs
+#: field:stock.picking,total_amount:0
+msgid "Total Product Price"
+msgstr "Gesamter Produktpreis"
+
+#. module: purchase_landed_costs
+#: field:stock.move,price_unit_net:0
+msgid "Purchase Price"
+msgstr "Kaufpreis"
+
+#. module: purchase_landed_costs
+#: field:purchase.order,landing_cost_lines:0
+#: field:stock.picking,landing_cost_lines:0
+msgid "Landing Cost Lines"
+msgstr "Einstandsnebenkostenzeilen"
+
+#. module: purchase_landed_costs
+#: constraint:stock.move:0
+msgid ""
+"Error: Negative quantities for location and/or lots are not allowed for this "
+"product or product category"
+msgstr "Fehler: negative Mengen sind für diesen Lagerort / Los nicht erlaubt"
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "None"
+msgstr "Keine"
+
+#. module: purchase_landed_costs
+#: field:product.template,landed_cost_type:0
+msgid "Distribution Type"
+msgstr "Verteilungsart"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_partial_move
+msgid "Partial Move Processing Wizard"
+msgstr "Assistent für Teillieferungen"
+
+#. module: purchase_landed_costs
+#: view:stock.picking:0
+msgid "Notes"
+msgstr "Notizen"
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,currency_id:0
+msgid "Secondary Currency"
+msgstr "Alternative Währung"
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "Value"
+msgstr "Betrag"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_purchase_order
+#: field:landed.cost.position,purchase_order_id:0
+msgid "Purchase Order"
+msgstr "Einkaufsauftrag"
+
+#. module: purchase_landed_costs
+#: field:purchase.order.line,landed_cost_line_ids:0
+#: field:stock.move,landed_cost_line_ids:0
+#: field:stock.picking,landed_cost_line_ids:0
+msgid "Landed Costs Positions"
+msgstr "Nebenkostenpositionen"
+
+#. module: purchase_landed_costs
+#: field:purchase.order.line,landing_costs_order:0
+msgid "Landing Costs from Order"
+msgstr "Nebenkosten vom Einkaufsauftrag"
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,amount:0
+msgid "Amount"
+msgstr "Betrag"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_product_category
+msgid "Product Category"
+msgstr "Produktkategorie"
+
+#. module: purchase_landed_costs
+#: sql_constraint:stock.picking:0
+msgid "Reference must be unique per Company!"
+msgstr "Referenz muss je Unternehmen eindeutig sein"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_partial_picking
+msgid "Partial Picking Processing Wizard"
+msgstr "Teillieferungsassistent"
+
+#. 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 ""
+"Definiert, ob der Wert je Mengeneinheit oder absolut gerechnet werden muss"
+
+#. module: purchase_landed_costs
+#: selection:product.template,landed_cost_type:0
+msgid "Quantity"
+msgstr "Menge"
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,product_id:0
+msgid "Landed Cost Name"
+msgstr "Nebenkosten Bezeichnung"
+
+#. module: purchase_landed_costs
+#: field:purchase.order,landed_cost_base_quantity:0
+#: field:stock.picking,landed_cost_base_quantity:0
+msgid "Landed Costs Base Quantity"
+msgstr "Nebenkosten - Megnenbasis"
+
+#. module: purchase_landed_costs
+#: help:product.category,landed_cost:0
+msgid ""
+"Checck this if you want to use landed cost calculation for average price for "
+"this catgory"
+msgstr ""
+"Aktivieren, wenn für diese Produktkategorie Einstandsnebenkosten berechnet "
+"werden sollen"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_product_template
+msgid "Product Template"
+msgstr "Produktvorlage"
+
+#. module: purchase_landed_costs
+#: model:ir.model,name:purchase_landed_costs.model_stock_move
+msgid "Stock Move"
+msgstr "Lagerbuchung"
+
+#. module: purchase_landed_costs
+#: constraint:product.category:0
+msgid "Error ! You cannot create recursive categories."
+msgstr "Fehler ! Sie dürfen keine rekurisven Kategorien anlegen."
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,amount_currency:0
+msgid "Amount Currency"
+msgstr "Währungsbetrag"
+
+#. module: purchase_landed_costs
+#: field:stock.move,landing_costs:0
+msgid "Line Landing Costs"
+msgstr "Nebenkosten Zeilen"
+
+#. module: purchase_landed_costs
+#: help:landed.cost.position,amount:0
+msgid ""
+"Landed cost for stock valuation. It will be added to the price of the "
+"supplier price."
+msgstr ""
+"Einstandskosten für die Produktbewertung. Diese werden zu dem Produktpreis "
+"hinzugerechnet."
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,partner_id:0
+msgid "Partner"
+msgstr "Partner"
+
+#. module: purchase_landed_costs
+#: field:purchase.order,landed_cost:0 field:stock.picking,landed_cost:0
+msgid "Landed Costs Total Untaxed"
+msgstr "EInstandspreise ohne Umsatzsteuer"
+
+#. module: purchase_landed_costs
+#: field:landed.cost.position,price_type:0
+msgid "Amount Type"
+msgstr "Berechnungsart"

=== 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-09 18:00:07 +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-09 18:00:07 +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 osv import osv, fields
+from tools.translate import _
+        
+
+class product_template(osv.osv):
+    _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(osv.osv):
+    _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-09 18:00:07 +0000
@@ -0,0 +1,436 @@
+# -*- 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 osv import osv, fields
+import decimal_precision as dp
+from tools.translate import _
+import logging
+
+
+class landed_cost_position(osv.osv):
+    """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 _amount_total(self, cr, uid, ids, name, args, context):
+    # 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.
+        if not ids : return {}
+        result = {}
+        # landed costss for the line
+        for line in self.browse(cr, uid, ids):
+            if line.purchase_order_line_id and line.price_type == 'per_unit':
+                result[line.id] = (line.amount * 
+                    line.purchase_order_line_id.product_qty)
+            else:
+                result[line.id] = line.amount
+        return result
+
+    _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,),
+        'amount': fields.float
+            ('Amount',
+            required=True,
+            digits_compute=dp.get_precision('Purchase Price'),
+            help="Landed cost for stock valuation (expressed in company default currency). "
+                 "It will be added to the price of the supplier price."),
+        '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_total': fields.function(
+            _amount_total,
+            digits_compute=dp.get_precision('Account'),
+            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",
+            store=True),
+        '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(osv.osv):
+    _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(osv.osv):
+    _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.currency_id.id or 
+                po.company_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 {
+            'partner_id' : landed_cost.partner_id.id,
+            'currency_id': currency_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-09 18:00:07 +0000
@@ -0,0 +1,212 @@
+<?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="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="Product" 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" 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-09 18:00:07 +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-09 18:00:07 +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-09 18:00:07 +0000
@@ -0,0 +1,63 @@
+# -*- 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 osv import osv, fields
+import decimal_precision as dp
+import logging
+
+
+class stock_move(osv.osv):
+    _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(osv.osv_memory):
+    _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.- but the new cost is still
+        #   in CHF...
+        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-09 18:00:07 +0000
@@ -0,0 +1,123 @@
+-
+  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
+    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-09 18:00:07 +0000
@@ -0,0 +1,123 @@
+-
+  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
+    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_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-09 18:00:07 +0000
@@ -0,0 +1,126 @@
+-
+  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
+    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