From 305f0ac3c21aaa890ea274e5745c37e26c7757f3 Mon Sep 17 00:00:00 2001
From: Julien Muchembled <jm@nexedi.com>
Date: Fri, 30 May 2008 15:08:29 +0000
Subject: [PATCH]  * Add support for unit conversion:    * resources are
 described using Measure objects    * stock can be queried in any unit    *
 movements perform unit conversion

 * See following wiki articles:
   * HowToUseMeasures
   * TechnicalNotesOnUnitConversion

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@21253 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../converted_inventory_report.xml            |  83 ++++
 .../portal_types/Component/view_measure.xml   |  83 ++++
 .../converted_inventory_report.xml            |  83 ++++
 .../portal_types/Product/view_measure.xml     |  83 ++++
 .../converted_inventory_report.xml            |  83 ++++
 .../portal_types/Service/view_measure.xml     |  83 ++++
 .../portal_categories/metric_type.xml         | 221 ++++++++++
 .../allowed_content_types.xml                 |   6 +
 .../hidden_content_type_list.xml              |   3 +
 .../portal_types/Measure%20Cell.xml           | 115 ++++++
 .../portal_types/Measure.xml                  | 115 ++++++
 .../workflow_chain_type.xml                   |   4 +
 .../portal_skins/erp5_pdm/Measure_view.xml    | 173 ++++++++
 .../erp5_pdm/Measure_view/matrixbox.xml       | 383 ++++++++++++++++++
 .../matrixbox_predicate_category_list.xml     | 319 +++++++++++++++
 .../Measure_view/matrixbox_quantity.xml       | 121 ++++++
 .../Measure_view/my_default_metric_type.xml   |  99 +++++
 ...y_measure_variation_base_category_list.xml | 141 +++++++
 .../erp5_pdm/Measure_view/my_metric_type.xml  | 132 ++++++
 .../erp5_pdm/Measure_view/my_quantity.xml     |  93 +++++
 .../Measure_view/my_quantity_unit.xml         | 159 ++++++++
 ...sourceModule_getConvertedInventoryList.xml | 151 +++++++
 ...sourceModule_getConvertedInventoryStat.xml | 142 +++++++
 .../erp5_pdm/ResourceModule_getSelection.xml  | 224 ++++++++++
 ...ule_viewConvertedInventoryReportDialog.xml | 152 +++++++
 .../listbox.xml                               | 247 +++++++++++
 .../your_metric_type.xml                      | 132 ++++++
 .../your_quantity_unit.xml                    | 132 ++++++
 .../my_quantity_unit_list.xml                 |  29 ++
 .../erp5_pdm/Resource_viewMeasure.xml         | 169 ++++++++
 .../erp5_pdm/Resource_viewMeasure/listbox.xml | 172 ++++++++
 .../listbox_default_metric_type.xml           |  93 +++++
 .../Resource_viewMeasure/listbox_quantity.xml |  93 +++++
 .../listbox_quantity_unit.xml                 | 150 +++++++
 .../my_quantity_unit_list.xml                 |  87 ++++
 .../measure_interaction_workflow.xml          |  43 ++
 .../interactions.xml                          |  37 ++
 .../interactions/Measure_updateCatalog.xml    |  94 +++++
 .../measure_interaction_workflow/scripts.xml  |  37 ++
 .../scripts/Measure_reindexResource.xml       | 141 +++++++
 .../variables.xml                             |  31 ++
 .../worklists.xml                             |  31 ++
 bt5/erp5_pdm/bt/revision                      |   2 +-
 bt5/erp5_pdm/bt/template_action_path_list     |   8 +-
 bt5/erp5_pdm/bt/template_base_category_list   |   1 +
 ...late_portal_type_allowed_content_type_list |   4 +
 ...plate_portal_type_hidden_content_type_list |   1 +
 bt5/erp5_pdm/bt/template_portal_type_id_list  |   2 +
 .../template_portal_type_workflow_chain_list  |   2 +
 bt5/erp5_pdm/bt/template_workflow_id_list     |   1 +
 .../Constraint/ResourceMeasuresConsistency.py | 115 ++++++
 product/ERP5/Document/Amount.py               |  44 +-
 product/ERP5/Document/Currency.py             |   4 +-
 product/ERP5/Document/Measure.py              | 285 +++++++++++++
 product/ERP5/Document/Movement.py             |  11 +-
 product/ERP5/Document/Resource.py             | 122 +++++-
 product/ERP5/PropertySheet/Measure.py         |  46 +++
 product/ERP5/PropertySheet/Resource.py        |   7 +
 product/ERP5/Tool/SimulationTool.py           |  77 +++-
 .../portal_categories/quantity_unit.xml       |   2 +-
 .../portal_skins/erp5_core/Category_view.xml  |   1 +
 .../erp5_core/Category_view/my_quantity.xml   | 163 ++++++++
 .../erp5_core/Resource_zGetInventoryList.xml  |  42 ++
 product/ERP5/bootstrap/erp5_core/bt/revision  |   2 +-
 .../z0_drop_measure.catalog_keys.xml          |   5 +
 .../erp5_mysql_innodb/z0_drop_measure.xml     | 115 ++++++
 .../z0_uncatalog_measure.catalog_keys.xml     |   5 +
 .../z0_uncatalog_measure.xml                  | 184 +++++++++
 .../z_catalog_measure_list.catalog_keys.xml   |  13 +
 .../z_catalog_measure_list.xml                | 224 ++++++++++
 .../z_create_measure.catalog_keys.xml         |   5 +
 .../erp5_mysql_innodb/z_create_measure.xml    | 165 ++++++++
 .../z_related_metric_type.catalog_keys.xml    |   2 +
 .../z_related_metric_type.xml                 | 164 ++++++++
 .../related_key_list.xml                      |   1 +
 .../erp5_mysql_innodb_catalog/bt/revision     |   2 +-
 .../bt/template_catalog_method_id_list        |   5 +
 .../bt/template_catalog_related_key_list      |   3 +-
 product/ERP5/tests/testInventoryAPI.py        | 117 +++++-
 product/ERP5Type/Utils.py                     |  99 +++++
 80 files changed, 6975 insertions(+), 45 deletions(-)
 create mode 100644 bt5/erp5_pdm/ActionTemplateItem/portal_types/Component%20Module/converted_inventory_report.xml
 create mode 100644 bt5/erp5_pdm/ActionTemplateItem/portal_types/Component/view_measure.xml
 create mode 100644 bt5/erp5_pdm/ActionTemplateItem/portal_types/Product%20Module/converted_inventory_report.xml
 create mode 100644 bt5/erp5_pdm/ActionTemplateItem/portal_types/Product/view_measure.xml
 create mode 100644 bt5/erp5_pdm/ActionTemplateItem/portal_types/Service%20Module/converted_inventory_report.xml
 create mode 100644 bt5/erp5_pdm/ActionTemplateItem/portal_types/Service/view_measure.xml
 create mode 100644 bt5/erp5_pdm/CategoryTemplateItem/portal_categories/metric_type.xml
 create mode 100644 bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure%20Cell.xml
 create mode 100644 bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_predicate_category_list.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_quantity.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_default_metric_type.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_measure_variation_base_category_list.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_metric_type.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity_unit.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryList.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryStat.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getSelection.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/listbox.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_metric_type.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_quantity_unit.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_default_metric_type.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity_unit.xml
 create mode 100644 bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/my_quantity_unit_list.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions/Measure_updateCatalog.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts/Measure_reindexResource.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/variables.xml
 create mode 100644 bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/worklists.xml
 create mode 100644 product/ERP5/Constraint/ResourceMeasuresConsistency.py
 create mode 100644 product/ERP5/Document/Measure.py
 create mode 100644 product/ERP5/PropertySheet/Measure.py
 create mode 100644 product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view/my_quantity.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.catalog_keys.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.catalog_keys.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.catalog_keys.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.catalog_keys.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.catalog_keys.xml
 create mode 100644 product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.xml

diff --git a/bt5/erp5_pdm/ActionTemplateItem/portal_types/Component%20Module/converted_inventory_report.xml b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Component%20Module/converted_inventory_report.xml
new file mode 100644
index 0000000000..c6e48a3d3d
--- /dev/null
+++ b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Component%20Module/converted_inventory_report.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>category</string> </key>
+            <value> <string>object_report</string> </value>
+        </item>
+        <item>
+            <key> <string>condition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>icon</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>converted_inventory_report</string> </value>
+        </item>
+        <item>
+            <key> <string>permissions</string> </key>
+            <value>
+              <tuple>
+                <string>View</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>priority</string> </key>
+            <value> <float>1.0</float> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Converted Inventory Report</string> </value>
+        </item>
+        <item>
+            <key> <string>visible</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="Expression" module="Products.CMFCore.Expression"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>text</string> </key>
+            <value> <string>string:${object_url}/ResourceModule_viewConvertedInventoryReportDialog</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/ActionTemplateItem/portal_types/Component/view_measure.xml b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Component/view_measure.xml
new file mode 100644
index 0000000000..d0c90a3fe7
--- /dev/null
+++ b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Component/view_measure.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>category</string> </key>
+            <value> <string>object_view</string> </value>
+        </item>
+        <item>
+            <key> <string>condition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>icon</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>view_measure</string> </value>
+        </item>
+        <item>
+            <key> <string>permissions</string> </key>
+            <value>
+              <tuple>
+                <string>View</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>priority</string> </key>
+            <value> <float>1.5</float> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Measure</string> </value>
+        </item>
+        <item>
+            <key> <string>visible</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="Expression" module="Products.CMFCore.Expression"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>text</string> </key>
+            <value> <string>string:${object_url}/Resource_viewMeasure</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/ActionTemplateItem/portal_types/Product%20Module/converted_inventory_report.xml b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Product%20Module/converted_inventory_report.xml
new file mode 100644
index 0000000000..c6e48a3d3d
--- /dev/null
+++ b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Product%20Module/converted_inventory_report.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>category</string> </key>
+            <value> <string>object_report</string> </value>
+        </item>
+        <item>
+            <key> <string>condition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>icon</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>converted_inventory_report</string> </value>
+        </item>
+        <item>
+            <key> <string>permissions</string> </key>
+            <value>
+              <tuple>
+                <string>View</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>priority</string> </key>
+            <value> <float>1.0</float> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Converted Inventory Report</string> </value>
+        </item>
+        <item>
+            <key> <string>visible</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="Expression" module="Products.CMFCore.Expression"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>text</string> </key>
+            <value> <string>string:${object_url}/ResourceModule_viewConvertedInventoryReportDialog</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/ActionTemplateItem/portal_types/Product/view_measure.xml b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Product/view_measure.xml
new file mode 100644
index 0000000000..d0c90a3fe7
--- /dev/null
+++ b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Product/view_measure.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>category</string> </key>
+            <value> <string>object_view</string> </value>
+        </item>
+        <item>
+            <key> <string>condition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>icon</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>view_measure</string> </value>
+        </item>
+        <item>
+            <key> <string>permissions</string> </key>
+            <value>
+              <tuple>
+                <string>View</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>priority</string> </key>
+            <value> <float>1.5</float> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Measure</string> </value>
+        </item>
+        <item>
+            <key> <string>visible</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="Expression" module="Products.CMFCore.Expression"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>text</string> </key>
+            <value> <string>string:${object_url}/Resource_viewMeasure</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/ActionTemplateItem/portal_types/Service%20Module/converted_inventory_report.xml b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Service%20Module/converted_inventory_report.xml
new file mode 100644
index 0000000000..c6e48a3d3d
--- /dev/null
+++ b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Service%20Module/converted_inventory_report.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>category</string> </key>
+            <value> <string>object_report</string> </value>
+        </item>
+        <item>
+            <key> <string>condition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>icon</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>converted_inventory_report</string> </value>
+        </item>
+        <item>
+            <key> <string>permissions</string> </key>
+            <value>
+              <tuple>
+                <string>View</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>priority</string> </key>
+            <value> <float>1.0</float> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Converted Inventory Report</string> </value>
+        </item>
+        <item>
+            <key> <string>visible</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="Expression" module="Products.CMFCore.Expression"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>text</string> </key>
+            <value> <string>string:${object_url}/ResourceModule_viewConvertedInventoryReportDialog</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/ActionTemplateItem/portal_types/Service/view_measure.xml b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Service/view_measure.xml
new file mode 100644
index 0000000000..d0c90a3fe7
--- /dev/null
+++ b/bt5/erp5_pdm/ActionTemplateItem/portal_types/Service/view_measure.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>category</string> </key>
+            <value> <string>object_view</string> </value>
+        </item>
+        <item>
+            <key> <string>condition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>icon</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>view_measure</string> </value>
+        </item>
+        <item>
+            <key> <string>permissions</string> </key>
+            <value>
+              <tuple>
+                <string>View</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>priority</string> </key>
+            <value> <float>1.5</float> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Measure</string> </value>
+        </item>
+        <item>
+            <key> <string>visible</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="Expression" module="Products.CMFCore.Expression"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>text</string> </key>
+            <value> <string>string:${object_url}/Resource_viewMeasure</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/CategoryTemplateItem/portal_categories/metric_type.xml b/bt5/erp5_pdm/CategoryTemplateItem/portal_categories/metric_type.xml
new file mode 100644
index 0000000000..c9d4fece96
--- /dev/null
+++ b/bt5/erp5_pdm/CategoryTemplateItem/portal_categories/metric_type.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="BaseCategory" module="Products.ERP5Type.Document.BaseCategory"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_count</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>_folder_handler</string> </key>
+            <value> <string>CMFBTreeFolderHandler</string> </value>
+        </item>
+        <item>
+            <key> <string>_mt_index</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_tree</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>acquisition_append_value</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>acquisition_base_category</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>acquisition_copy_value</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>acquisition_mask_value</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+        <item>
+            <key> <string>acquisition_object_id</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>acquisition_portal_type</string> </key>
+            <value> <string>python:[]</string> </value>
+        </item>
+        <item>
+            <key> <string>acquisition_sync_value</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>categories</string> </key>
+            <value>
+              <tuple>
+                <string>metric_type</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>category_type</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>criterion_property</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>fallback_base_category</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>id_generator</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id_group</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>last_id</string> </key>
+            <value> <string>3</string> </value>
+        </item>
+        <item>
+            <key> <string>membership_criterion_base_category</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>membership_criterion_category</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>multimembership_criterion_base_category</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>portal_type</string> </key>
+            <value> <string>Base Category</string> </value>
+        </item>
+        <item>
+            <key> <string>read_permission</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>rid</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>short_title</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>sid</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>test_method_id</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>uid</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>write_permission</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Length" module="BTrees.Length"/>
+    </pickle>
+    <pickle> <int>0</int> </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="OOBTree" module="BTrees._OOBTree"/>
+    </pickle>
+    <pickle>
+      <none/>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="OOBTree" module="BTrees._OOBTree"/>
+    </pickle>
+    <pickle>
+      <none/>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml b/bt5/erp5_pdm/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml
index ab8104db70..5342abd241 100644
--- a/bt5/erp5_pdm/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml
+++ b/bt5/erp5_pdm/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml
@@ -1,5 +1,6 @@
 <allowed_content_type_list>
  <portal_type id="Component">
+  <item>Measure</item>
   <item>Sale Supply Line</item>
   <item>Supply Line</item>
   <item>Image</item>
@@ -9,7 +10,11 @@
  <portal_type id="Component Module">
   <item>Component</item>
  </portal_type>
+ <portal_type id="Measure">
+  <item>Measure Cell</item>
+ </portal_type>
  <portal_type id="Product">
+  <item>Measure</item>
   <item>Sale Supply Line</item>
   <item>Supply Line</item>
   <item>Image</item>
@@ -46,6 +51,7 @@
   <item>Service Individual Variation</item>
   <item>Purchase Supply Line</item>
   <item>Sale Supply Line</item>
+  <item>Measure</item>
  </portal_type>
  <portal_type id="Service Module">
   <item>Service</item>
diff --git a/bt5/erp5_pdm/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml b/bt5/erp5_pdm/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml
index 2e6864e5d3..ce0218c90a 100644
--- a/bt5/erp5_pdm/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml
+++ b/bt5/erp5_pdm/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml
@@ -5,6 +5,9 @@
   <item>Supply Line</item>
   <item>Image</item>
  </portal_type>
+ <portal_type id="Measure">
+  <item>Measure Cell</item>
+ </portal_type>
  <portal_type id="Product">
   <item>Image</item>
   <item>Sale Supply Line</item>
diff --git a/bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure%20Cell.xml b/bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure%20Cell.xml
new file mode 100644
index 0000000000..99759c0398
--- /dev/null
+++ b/bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure%20Cell.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ERP5TypeInformation" module="Products.ERP5Type.ERP5Type"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_actions</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_aliases</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_roles</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>acquire_local_roles</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>allowed_content_types</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>base_category_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_icon</string> </key>
+            <value> <string>document_icon.gif</string> </value>
+        </item>
+        <item>
+            <key> <string>content_meta_type</string> </key>
+            <value> <string>ERP5 Mapped Value</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>factory</string> </key>
+            <value> <string>addMappedValue</string> </value>
+        </item>
+        <item>
+            <key> <string>filter_content_types</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>hidden_content_type_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Measure Cell</string> </value>
+        </item>
+        <item>
+            <key> <string>init_script</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>permission</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>property_sheet_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure.xml b/bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure.xml
new file mode 100644
index 0000000000..485ca8f02e
--- /dev/null
+++ b/bt5/erp5_pdm/PortalTypeTemplateItem/portal_types/Measure.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ERP5TypeInformation" module="Products.ERP5Type.ERP5Type"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_actions</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_aliases</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_roles</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>acquire_local_roles</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>allowed_content_types</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>base_category_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>content_icon</string> </key>
+            <value> <string>document_icon.gif</string> </value>
+        </item>
+        <item>
+            <key> <string>content_meta_type</string> </key>
+            <value> <string>ERP5 Measure</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>factory</string> </key>
+            <value> <string>addMeasure</string> </value>
+        </item>
+        <item>
+            <key> <string>filter_content_types</string> </key>
+            <value> <int>1</int> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>hidden_content_type_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Measure</string> </value>
+        </item>
+        <item>
+            <key> <string>init_script</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>permission</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>property_sheet_list</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml b/bt5/erp5_pdm/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
index b9a5a62f4c..ee523c0ec5 100644
--- a/bt5/erp5_pdm/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
+++ b/bt5/erp5_pdm/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
@@ -3,6 +3,10 @@
   <type>Component</type>
   <workflow>validation_workflow, edit_workflow</workflow>
  </chain>
+ <chain>
+  <type>Measure</type>
+  <workflow>edit_workflow, measure_interaction_workflow</workflow>
+ </chain>
  <chain>
   <type>Product</type>
   <workflow>validation_workflow, edit_workflow</workflow>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view.xml
new file mode 100644
index 0000000000..f10a8cecf3
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ERP5Form" module="Products.ERP5Form.Form"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value> <string>Base_edit</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>edit_order</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>enctype</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <list>
+                <string>left</string>
+                <string>right</string>
+                <string>center</string>
+                <string>bottom</string>
+                <string>hidden</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>bottom</string> </key>
+                    <value>
+                      <list>
+                        <string>matrixbox</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>center</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value>
+                      <list>
+                        <string>matrixbox_quantity</string>
+                        <string>matrixbox_predicate_category_list</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>left</string> </key>
+                    <value>
+                      <list>
+                        <string>my_metric_type</string>
+                        <string>my_default_metric_type</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>right</string> </key>
+                    <value>
+                      <list>
+                        <string>my_quantity</string>
+                        <string>my_quantity_unit</string>
+                        <string>my_measure_variation_base_category_list</string>
+                      </list>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Measure_view</string> </value>
+        </item>
+        <item>
+            <key> <string>method</string> </key>
+            <value> <string>POST</string> </value>
+        </item>
+        <item>
+            <key> <string>name</string> </key>
+            <value> <string>Measure_view</string> </value>
+        </item>
+        <item>
+            <key> <string>pt</string> </key>
+            <value> <string>form_view</string> </value>
+        </item>
+        <item>
+            <key> <string>row_length</string> </key>
+            <value> <int>4</int> </value>
+        </item>
+        <item>
+            <key> <string>stored_encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>unicode_mode</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>update_action</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox.xml
new file mode 100644
index 0000000000..e1ddffa6b7
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox.xml
@@ -0,0 +1,383 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="MatrixBox" module="Products.ERP5Form.MatrixBox"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>matrixbox</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_base_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_portal_type</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable_attributes</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>getter_method</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>global_attributes</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>lines</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>tabs</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>update_cell_range</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_base_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_portal_type</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable_attributes</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>getter_method</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>global_attributes</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>lines</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>tabs</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>update_cell_range</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>all_editable_attributes</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>target_quantity</string>
+                          <string>quantity</string>
+                        </tuple>
+                        <tuple>
+                          <string>price</string>
+                          <string>price</string>
+                        </tuple>
+                        <tuple>
+                          <string>predicate_value</string>
+                          <string>predicate_value</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_base_id</string> </key>
+                    <value> <string>cell</string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_portal_type</string> </key>
+                    <value> <string>Measure Cell</string> </value>
+                </item>
+                <item>
+                    <key> <string>cell_range</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>editable_attributes</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>quantity</string>
+                          <string>quantity</string>
+                        </tuple>
+                        <tuple>
+                          <string>predicate_category_list</string>
+                          <string>predicate_category_list</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>getter_method</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>global_attributes</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>lines</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>tabs</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>matrixbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>update_cell_range</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.getVariationRangeCategoryItemList(1)</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>here/getMeasureVariationBaseCategoryList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.getVariationRangeCategoryItemList(0)</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.getVariationRangeCategoryItemList(2)</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_predicate_category_list.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_predicate_category_list.xml
new file mode 100644
index 0000000000..5061a17bd2
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_predicate_category_list.xml
@@ -0,0 +1,319 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="LinesField" module="Products.Formulator.StandardFields"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>matrixbox_predicate_category_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+                <item>
+                    <key> <string>line_too_long</string> </key>
+                    <value> <string>A line was too long.</string> </value>
+                </item>
+                <item>
+                    <key> <string>required_not_found</string> </key>
+                    <value> <string>Input is required but no input given.</string> </value>
+                </item>
+                <item>
+                    <key> <string>too_long</string> </key>
+                    <value> <string>You entered too many characters.</string> </value>
+                </item>
+                <item>
+                    <key> <string>too_many_lines</string> </key>
+                    <value> <string>You entered too many lines.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>extra</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>height</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_length</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_linelength</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_lines</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>required</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>unicode</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>view_separator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>whitespace_preserve</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>width</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>extra</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>height</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_length</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_linelength</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_lines</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>required</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>unicode</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>view_separator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>whitespace_preserve</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>width</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>extra</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>height</string> </key>
+                    <value> <int>5</int> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>max_length</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_linelength</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>max_lines</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>required</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>matrixbox_predicate_value</string> </value>
+                </item>
+                <item>
+                    <key> <string>unicode</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>view_separator</string> </key>
+                    <value> <string encoding="cdata"><![CDATA[
+
+<br />
+
+]]></string> </value>
+                </item>
+                <item>
+                    <key> <string>whitespace_preserve</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>width</string> </key>
+                    <value> <int>40</int> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: cell_index</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_quantity.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_quantity.xml
new file mode 100644
index 0000000000..fc08b7b92f
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/matrixbox_quantity.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>default</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>matrixbox_quantity</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_quantity</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: cell is not None and cell.getQuantity() or \'\'</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_default_metric_type.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_default_metric_type.xml
new file mode 100644
index 0000000000..3aa4952e5d
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_default_metric_type.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_default_metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_checkbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Default Metric Type</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_measure_variation_base_category_list.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_measure_variation_base_category_list.xml
new file mode 100644
index 0000000000..ec21205c55
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_measure_variation_base_category_list.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>items</string>
+                <string>size</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_measure_variation_base_category_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key>                 <string>size</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_multi_list_field</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>size</string> </key>
+                    <value> <int>3</int> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Variation Axes</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.getResourceValue().getVariationBaseCategoryItemList(omit_optional_variation=1)</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_metric_type.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_metric_type.xml
new file mode 100644
index 0000000000..34fc04322d
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_metric_type.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>items</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_category</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Metric Type</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: getattr(here.portal_categories[field.getId().split(\'_\',1)[1]], preferences.getPreference(\'preferred_category_child_item_list_method_id\', \'getCategoryChildCompactLogicalPathItemList\'))(display_none_category=1, local_sort_id=(\'int_index\', \'translated_title\'), checked_permission=\'View\')</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity.xml
new file mode 100644
index 0000000000..66bcdb5a5a
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_quantity</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_quantity</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity_unit.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity_unit.xml
new file mode 100644
index 0000000000..1352ee20b9
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Measure_view/my_quantity_unit.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>default</string>
+                <string>items</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_quantity_unit</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key>                 <string>default</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_category</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Quantity Unit</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>here/getLocalQuantityUnit</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>here/getQuantityUnitItemList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryList.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryList.xml
new file mode 100644
index 0000000000..7f3f58b738
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryList.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Python_magic</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>kw[\'resource_uid\'] = context.ResourceModule_getSelection().getUidList()\n
+\n
+if kw.setdefault(\'inventory_list\', 1):\n
+  kw.update(group_by_node = 1, group_by_resource = 0)\n
+else:\n
+  kw.update(ignore_group_by = 1)\n
+\n
+return context.getPortalObject().portal_simulation \\\n
+              .getConvertedInventoryList(simulation_period=\'All\', **kw)\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_code</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_filepath</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>**kw</string> </value>
+        </item>
+        <item>
+            <key> <string>errors</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_code</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="FuncCode" module="Shared.DC.Scripts.Signature"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>co_argcount</string> </key>
+                        <value> <int>0</int> </value>
+                    </item>
+                    <item>
+                        <key> <string>co_varnames</string> </key>
+                        <value>
+                          <tuple>
+                            <string>kw</string>
+                            <string>_getattr_</string>
+<string>context</string>
+                            <string>_write_</string>
+                            <string>_apply_</string>
+                          </tuple>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_defaults</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>ResourceModule_getConvertedInventoryList</string> </value>
+        </item>
+        <item>
+            <key> <string>warnings</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryStat.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryStat.xml
new file mode 100644
index 0000000000..27a2bedfdb
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getConvertedInventoryStat.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Python_magic</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>return context.ResourceModule_getConvertedInventoryList(inventory_list=0, **kw)\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_code</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_filepath</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>**kw</string> </value>
+        </item>
+        <item>
+            <key> <string>errors</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_code</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="FuncCode" module="Shared.DC.Scripts.Signature"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>co_argcount</string> </key>
+                        <value> <int>0</int> </value>
+                    </item>
+                    <item>
+                        <key> <string>co_varnames</string> </key>
+                        <value>
+                          <tuple>
+                            <string>kw</string>
+                            <string>_apply_</string>
+                            <string>_getattr_</string>
+<string>context</string>
+                          </tuple>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_defaults</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>ResourceModule_getConvertedInventoryStat</string> </value>
+        </item>
+        <item>
+            <key> <string>warnings</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getSelection.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getSelection.xml
new file mode 100644
index 0000000000..b637315b50
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_getSelection.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Python_magic</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string># JM: a \'preferred_category_display_method_id\' preference would be better\n
+\n
+def getPreferredCategoryChildItemListMethodId():\n
+  return context.getPortalObject().portal_preferences.getPreference(\n
+    \'preferred_category_child_item_list_method_id\',\n
+    \'getCategoryChildCompactLogicalPathItemList\')\n
+\n
+def getPreferredCategoryDisplayMethodId():\n
+  method = \'get\' + getPreferredCategoryChildItemListMethodId() \\\n
+                   [ len(\'getCategoryChild\') : - len(\'ItemList\') ]\n
+  return method == \'getTranslatedCompactTitle\' and \'getCompactTranslatedTitle\' \\\n
+      or method\n
+\n
+# Zope: waiting for __builtin__.set\n
+set = lambda seq: dict((k,None) for k in seq).iterkeys()\n
+\n
+# Zope: waiting for __builtin__.sorted\n
+def sorted(seq):\n
+  l = list(seq)\n
+  l.sort()\n
+  return l\n
+\n
+class ResourceSelection:\n
+  """\n
+  Helper class to handle a selection of resources.\n
+  """\n
+  def getCommonMetricTypeList(self):\n
+    """\n
+    Get the list of metric_type categories\n
+    that are common to all selected resources.\n
+    """\n
+    return [ metric_type[\'relative_url\'].split(\'/\',1)[1]\n
+              for metric_type in self.context.\n
+                ResourceModule_zGetCommonMetricTypeList(\n
+                  resource_uid = self.getUidList()) ]\n
+\n
+  def getCommonBaseQuantityUnitSet(self):\n
+    """\n
+    Get the set of possible quantity_unit categories\n
+    for the list of metric_type returned by getCommonMetricTypeList.\n
+    """\n
+    return set([mt.split(\'/\',1)[0] for mt in self.getCommonMetricTypeList()])\n
+\n
+  def getCommonMetricTypeItemList(self):\n
+    """\n
+    Similar to getCommonMetricTypeList\n
+    but return the categories as a list of tuples (title, id).\n
+    This is mostly useful in ERP5Form instances to generate selection menus.\n
+    """\n
+    traverse = self.portal.portal_categories[\'metric_type\'].restrictedTraverse\n
+    display = getPreferredCategoryDisplayMethodId()\n
+    return sorted((getattr(traverse(metric_type),display)(), metric_type)\n
+      for metric_type in self.getCommonMetricTypeList())\n
+\n
+  def getCommonQuantityUnitItemList(self):\n
+    """\n
+    Similar to getCommonBaseQuantityUnitSet\n
+    but return the categories as a list of tuples (title, id).\n
+    This is mostly useful in ERP5Form instances to generate selection menus.\n
+    """\n
+    traverse = self.portal.portal_categories[\'quantity_unit\'].restrictedTraverse\n
+    display = getPreferredCategoryChildItemListMethodId()\n
+    common_quantity_unit_item_list = []\n
+    for qu in sorted(self.getCommonBaseQuantityUnitSet()):\n
+      common_quantity_unit_item_list.extend(getattr(traverse(qu),display)\n
+        (display_none_category=0, local_sort_id=\'quantity\'))\n
+    return common_quantity_unit_item_list\n
+\n
+self = ResourceSelection()\n
+self.context = context\n
+self.portal = context.getPortalObject()\n
+uid_list = self.portal.portal_selections \\\n
+               .getSelectionCheckedUidsFor(context.REQUEST.selection_name)\n
+if not uid_list:\n
+  raise ValueError(\'No resource selected.\')\n
+self.getUidList = lambda: uid_list\n
+\n
+return self\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_code</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_filepath</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>errors</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_code</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="FuncCode" module="Shared.DC.Scripts.Signature"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>co_argcount</string> </key>
+                        <value> <int>0</int> </value>
+                    </item>
+                    <item>
+                        <key> <string>co_varnames</string> </key>
+                        <value>
+                          <tuple>
+                            <string>getPreferredCategoryChildItemListMethodId</string>
+                            <string>getPreferredCategoryDisplayMethodId</string>
+                            <string>set</string>
+                            <string>sorted</string>
+                            <string>ResourceSelection</string>
+                            <string>self</string>
+                            <string>context</string>
+                            <string>_write_</string>
+                            <string>_getattr_</string>
+                            <string>portal</string>
+                            <string>uid_list</string>
+                            <string>ValueError</string>
+                            <string>getUidList</string>
+                          </tuple>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_defaults</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>ResourceModule_getSelection</string> </value>
+        </item>
+        <item>
+            <key> <string>warnings</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog.xml
new file mode 100644
index 0000000000..2f7d1e4aa3
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ERP5Form" module="Products.ERP5Form.Form"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value> <string>ResourceModule_viewConvertedInventoryReportDialog</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>edit_order</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>enctype</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <list>
+                <string>left</string>
+                <string>hidden</string>
+                <string>bottom</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>bottom</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>left</string> </key>
+                    <value>
+                      <list>
+                        <string>your_metric_type</string>
+                        <string>your_quantity_unit</string>
+                      </list>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>ResourceModule_viewConvertedInventoryReportDialog</string> </value>
+        </item>
+        <item>
+            <key> <string>method</string> </key>
+            <value> <string>POST</string> </value>
+        </item>
+        <item>
+            <key> <string>name</string> </key>
+            <value> <string>ResourceModule_viewConvertedInventoryReportDialog</string> </value>
+        </item>
+        <item>
+            <key> <string>pt</string> </key>
+            <value> <string>form_view_dialog</string> </value>
+        </item>
+        <item>
+            <key> <string>row_length</string> </key>
+            <value> <int>4</int> </value>
+        </item>
+        <item>
+            <key> <string>stored_encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Converted Inventory Report</string> </value>
+        </item>
+        <item>
+            <key> <string>unicode_mode</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>update_action</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/listbox.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/listbox.xml
new file mode 100644
index 0000000000..c0d38aaefa
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/listbox.xml
@@ -0,0 +1,247 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>columns</string>
+                <string>list_method</string>
+                <string>stat_method</string>
+                <string>stat_columns</string>
+                <string>enabled</string>
+                <string>editable</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>list_method</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>stat_method</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>all_editable_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key>                 <string>columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>node_title</string>
+                          <string>Site or Warehouse</string>
+                        </tuple>
+                        <tuple>
+                          <string>current_converted_quantity</string>
+                          <string>Current</string>
+                        </tuple>
+                        <tuple>
+                          <string>available_converted_quantity</string>
+                          <string>Available</string>
+                        </tuple>
+                        <tuple>
+                          <string>future_converted_quantity</string>
+                          <string>Future</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key>                 <string>editable</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key>                 <string>enabled</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_listbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key>                 <string>list_method</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key>                 <string>stat_columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>current_converted_quantity</string>
+                          <string>current_converted_quantity</string>
+                        </tuple>
+                        <tuple>
+                          <string>available_converted_quantity</string>
+                          <string>available_converted_quantity</string>
+                        </tuple>
+                        <tuple>
+                          <string>future_converted_quantity</string>
+                          <string>future_converted_quantity</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key>                 <string>stat_method</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key>                 <string>title</string> </key>
+                    <value> <string>Stock</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: (lambda mt, qu: mt and qu and mt.split(\'/\')[0] == qu.split(\'/\')[0])(request.get(\'metric_type\'), request.get(\'quantity_unit\'))</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <tuple>
+        <global name="Method" module="Products.Formulator.MethodField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>method_name</string> </key>
+            <value> <string>ResourceModule_getConvertedInventoryList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <tuple>
+        <global name="Method" module="Products.Formulator.MethodField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>method_name</string> </key>
+            <value> <string>ResourceModule_getConvertedInventoryStat</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_metric_type.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_metric_type.xml
new file mode 100644
index 0000000000..1364e21c06
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_metric_type.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>items</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>your_metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_category</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Metric Type</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.ResourceModule_getSelection().getCommonMetricTypeItemList()</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_quantity_unit.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_quantity_unit.xml
new file mode 100644
index 0000000000..12e85512fd
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/ResourceModule_viewConvertedInventoryReportDialog/your_quantity_unit.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>items</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>your_quantity_unit</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_category</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Quantity Unit</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.ResourceModule_getSelection().getCommonQuantityUnitItemList()</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewFieldLibrary/my_quantity_unit_list.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewFieldLibrary/my_quantity_unit_list.xml
index a1af93c7ac..26a9b1f9b2 100644
--- a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewFieldLibrary/my_quantity_unit_list.xml
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewFieldLibrary/my_quantity_unit_list.xml
@@ -14,6 +14,7 @@
             <value>
               <list>
                 <string>title</string>
+                <string>items</string>
               </list>
             </value>
         </item>
@@ -63,6 +64,12 @@
                     <key> <string>form_id</string> </key>
                     <value> <string></string> </value>
                 </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
                 <item>
                     <key> <string>target</string> </key>
                     <value> <string></string> </value>
@@ -86,6 +93,12 @@
                     <key> <string>form_id</string> </key>
                     <value> <string>Base_viewFieldLibrary</string> </value>
                 </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
                 <item>
                     <key> <string>target</string> </key>
                     <value> <string>Click to edit the target</string> </value>
@@ -100,4 +113,20 @@
       </dictionary>
     </pickle>
   </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: here.portal_categories[\'quantity_unit\'].getCategoryChildCompactLogicalPathItemList(local_sort_id=(\'int_index\', \'translated_title\'), checked_permission=\'View\', filter_node=1)</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
 </ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure.xml
new file mode 100644
index 0000000000..4af303d4f8
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ERP5Form" module="Products.ERP5Form.Form"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value> <string>Base_edit</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>edit_order</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>enctype</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <list>
+                <string>left</string>
+                <string>right</string>
+                <string>center</string>
+                <string>bottom</string>
+                <string>hidden</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>bottom</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>center</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox_quantity_unit</string>
+                        <string>listbox_quantity</string>
+                        <string>listbox_default_metric_type</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>left</string> </key>
+                    <value>
+                      <list>
+                        <string>my_quantity_unit_list</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>right</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Resource_viewMeasure</string> </value>
+        </item>
+        <item>
+            <key> <string>method</string> </key>
+            <value> <string>POST</string> </value>
+        </item>
+        <item>
+            <key> <string>name</string> </key>
+            <value> <string>Product_viewQuantityUnit</string> </value>
+        </item>
+        <item>
+            <key> <string>pt</string> </key>
+            <value> <string>form_view</string> </value>
+        </item>
+        <item>
+            <key> <string>row_length</string> </key>
+            <value> <int>4</int> </value>
+        </item>
+        <item>
+            <key> <string>stored_encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>unicode_mode</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>update_action</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox.xml
new file mode 100644
index 0000000000..aafa765730
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>title</string>
+                <string>columns</string>
+                <string>selection_name</string>
+                <string>portal_types</string>
+                <string>default_params</string>
+                <string>anchor</string>
+                <string>editable_columns</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>anchor</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>metric_type_logical_path</string>
+                          <string>Metric Type</string>
+                        </tuple>
+                        <tuple>
+                          <string>quantity_unit</string>
+                          <string>Quantity Unit</string>
+                        </tuple>
+                        <tuple>
+                          <string>quantity</string>
+                          <string>Quantity</string>
+                        </tuple>
+                        <tuple>
+                          <string>default_metric_type</string>
+                          <string>Default</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>default_params</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>editable_columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>quantity_unit</string>
+                          <string>quantity_unit</string>
+                        </tuple>
+                        <tuple>
+                          <string>quantity</string>
+                          <string>quantity</string>
+                        </tuple>
+                        <tuple>
+                          <string>default_metric_type</string>
+                          <string>default_metric_type</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_listbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>portal_types</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>Measure</string>
+                          <string>Measure</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>selection_name</string> </key>
+                    <value> <string>product_measure_selection</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Measures</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_default_metric_type.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_default_metric_type.xml
new file mode 100644
index 0000000000..d54c8fce6e
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_default_metric_type.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_default_metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_checkbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity.xml
new file mode 100644
index 0000000000..2fa6893381
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_quantity</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_quantity</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Measure_view</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity_unit.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity_unit.xml
new file mode 100644
index 0000000000..9099e6c00c
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/listbox_quantity_unit.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>default</string>
+                <string>items</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_quantity_unit</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key>                 <string>default</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key>                 <string>items</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_quantity_unit</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Measure_view</string> </value>
+                </item>
+                <item>
+                    <key> <string>items</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>cell/getLocalQuantityUnit</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>cell/getQuantityUnitItemList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/my_quantity_unit_list.xml b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/my_quantity_unit_list.xml
new file mode 100644
index 0000000000..e2e249e077
--- /dev/null
+++ b/bt5/erp5_pdm/SkinTemplateItem/portal_skins/erp5_pdm/Resource_viewMeasure/my_quantity_unit_list.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_quantity_unit_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_quantity_unit_list</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Product_view</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow.xml
new file mode 100644
index 0000000000..be6cbf4c45
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="InteractionWorkflowDefinition" module="Products.ERP5.InteractionWorkflow"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>measure_interaction_workflow</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions.xml
new file mode 100644
index 0000000000..879a78b540
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="Interaction" module="Products.ERP5.Interaction"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>interactions</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions/Measure_updateCatalog.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions/Measure_updateCatalog.xml
new file mode 100644
index 0000000000..817dc69e82
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/interactions/Measure_updateCatalog.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>actbox_category</string> </key>
+            <value> <string>workflow</string> </value>
+        </item>
+        <item>
+            <key> <string>actbox_name</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>actbox_url</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>activate_script_name</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>after_script_name</string> </key>
+            <value>
+              <list>
+                <string>Measure_reindexResource</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>guard</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Measure_updateCatalog</string> </value>
+        </item>
+        <item>
+            <key> <string>method_id</string> </key>
+            <value>
+              <list>
+                <string>unindexObject</string>
+                <string>reindexObject</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>once_per_transaction</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>portal_type_filter</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>script_name</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>trigger_type</string> </key>
+            <value> <int>2</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts.xml
new file mode 100644
index 0000000000..66683dde04
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="Scripts" module="Products.DCWorkflow.Scripts"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>scripts</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts/Measure_reindexResource.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts/Measure_reindexResource.xml
new file mode 100644
index 0000000000..c5a3e24d10
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/scripts/Measure_reindexResource.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Python_magic</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>state_change[\'object\'].getResourceValue().reindexObject()\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_code</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_filepath</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>state_change</string> </value>
+        </item>
+        <item>
+            <key> <string>errors</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_code</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="FuncCode" module="Shared.DC.Scripts.Signature"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>co_argcount</string> </key>
+                        <value> <int>1</int> </value>
+                    </item>
+                    <item>
+                        <key> <string>co_varnames</string> </key>
+                        <value>
+                          <tuple>
+                            <string>state_change</string>
+                            <string>_getattr_</string>
+                            <string>_getitem_</string>
+                          </tuple>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>func_defaults</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Measure_reindexResource</string> </value>
+        </item>
+        <item>
+            <key> <string>warnings</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/variables.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/variables.xml
new file mode 100644
index 0000000000..733d9ce458
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/variables.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="Variables" module="Products.DCWorkflow.Variables"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>variables</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/worklists.xml b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/worklists.xml
new file mode 100644
index 0000000000..3953ad0209
--- /dev/null
+++ b/bt5/erp5_pdm/WorkflowTemplateItem/portal_workflow/measure_interaction_workflow/worklists.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="Worklists" module="Products.DCWorkflow.Worklists"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>worklists</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_pdm/bt/revision b/bt5/erp5_pdm/bt/revision
index d25720879e..95c8a676e9 100644
--- a/bt5/erp5_pdm/bt/revision
+++ b/bt5/erp5_pdm/bt/revision
@@ -1 +1 @@
-112
\ No newline at end of file
+113
\ No newline at end of file
diff --git a/bt5/erp5_pdm/bt/template_action_path_list b/bt5/erp5_pdm/bt/template_action_path_list
index 8fe3ded4fb..80f6753fc6 100644
--- a/bt5/erp5_pdm/bt/template_action_path_list
+++ b/bt5/erp5_pdm/bt/template_action_path_list
@@ -1,14 +1,19 @@
 Component Individual Variation | view
+Component Module | converted_inventory_report
 Component Module | view
 Component | purchase_price_view
 Component | sale_price_view
 Component | view
 Component | view_flow_capacity
+Component | view_measure
+Preference | pdm_preference
 Product Individual Variation | view
+Product Module | converted_inventory_report
 Product Module | view
 Product | purchase_price_view
 Product | sale_price_view
 Product | view
+Product | view_measure
 Product | view_stock
 Purchase Supply Line | additional_price
 Purchase Supply Line | base_price
@@ -31,10 +36,12 @@ Sale Supply Line | view
 Sale Supply Module | view
 Sale Supply | view
 Service Individual Variation | view
+Service Module | converted_inventory_report
 Service Module | view
 Service | purchase_price_view
 Service | sale_price_view
 Service | view
+Service | view_measure
 Supply Line | additional_price
 Supply Line | base_price
 Supply Line | discount_ratio
@@ -43,7 +50,6 @@ Supply Line | non_discountable_additional_price
 Supply Line | surcharge_ratio
 Supply Line | variable_additional_price
 Supply Line | view
-System Preference | pdm_preference
 Transformation Module | view
 Transformation Operation | complete_quantity_matrix
 Transformation Operation | view
diff --git a/bt5/erp5_pdm/bt/template_base_category_list b/bt5/erp5_pdm/bt/template_base_category_list
index a6b90fc6e1..f641926346 100644
--- a/bt5/erp5_pdm/bt/template_base_category_list
+++ b/bt5/erp5_pdm/bt/template_base_category_list
@@ -7,6 +7,7 @@ feature
 image
 industrial_phase
 measure
+metric_type
 morphology
 operation
 option
diff --git a/bt5/erp5_pdm/bt/template_portal_type_allowed_content_type_list b/bt5/erp5_pdm/bt/template_portal_type_allowed_content_type_list
index db7c0a357e..82cd85577b 100644
--- a/bt5/erp5_pdm/bt/template_portal_type_allowed_content_type_list
+++ b/bt5/erp5_pdm/bt/template_portal_type_allowed_content_type_list
@@ -1,11 +1,14 @@
 Component Module | Component
 Component | Component Individual Variation
 Component | Image
+Component | Measure
 Component | Purchase Supply Line
 Component | Sale Supply Line
 Component | Supply Line
+Measure | Measure Cell
 Product Module | Product
 Product | Image
+Product | Measure
 Product | Product Individual Variation
 Product | Purchase Supply Line
 Product | Sale Supply Line
@@ -21,6 +24,7 @@ Sale Supply Module | Sale Supply
 Sale Supply | Sale Supply Line
 Sale Supply | Supply Line
 Service Module | Service
+Service | Measure
 Service | Purchase Supply Line
 Service | Sale Supply Line
 Service | Service Individual Variation
diff --git a/bt5/erp5_pdm/bt/template_portal_type_hidden_content_type_list b/bt5/erp5_pdm/bt/template_portal_type_hidden_content_type_list
index d787199025..acb7628187 100644
--- a/bt5/erp5_pdm/bt/template_portal_type_hidden_content_type_list
+++ b/bt5/erp5_pdm/bt/template_portal_type_hidden_content_type_list
@@ -2,6 +2,7 @@ Component | Image
 Component | Purchase Supply Line
 Component | Sale Supply Line
 Component | Supply Line
+Measure | Measure Cell
 Product | Image
 Product | Purchase Supply Line
 Product | Sale Supply Line
diff --git a/bt5/erp5_pdm/bt/template_portal_type_id_list b/bt5/erp5_pdm/bt/template_portal_type_id_list
index 0d5ad57d2c..340a94d16e 100644
--- a/bt5/erp5_pdm/bt/template_portal_type_id_list
+++ b/bt5/erp5_pdm/bt/template_portal_type_id_list
@@ -1,6 +1,8 @@
 Component
 Component Individual Variation
 Component Module
+Measure
+Measure Cell
 Product
 Product Individual Variation
 Product Module
diff --git a/bt5/erp5_pdm/bt/template_portal_type_workflow_chain_list b/bt5/erp5_pdm/bt/template_portal_type_workflow_chain_list
index 2a73c11913..0fcb1c9b0d 100644
--- a/bt5/erp5_pdm/bt/template_portal_type_workflow_chain_list
+++ b/bt5/erp5_pdm/bt/template_portal_type_workflow_chain_list
@@ -1,5 +1,7 @@
 Component | edit_workflow
 Component | validation_workflow
+Measure | edit_workflow
+Measure | measure_interaction_workflow
 Product | edit_workflow
 Product | validation_workflow
 Purchase Supply Line | edit_workflow
diff --git a/bt5/erp5_pdm/bt/template_workflow_id_list b/bt5/erp5_pdm/bt/template_workflow_id_list
index 1e5aed0648..974c4019d5 100644
--- a/bt5/erp5_pdm/bt/template_workflow_id_list
+++ b/bt5/erp5_pdm/bt/template_workflow_id_list
@@ -1 +1,2 @@
+measure_interaction_workflow
 supply_line_interaction_workflow
\ No newline at end of file
diff --git a/product/ERP5/Constraint/ResourceMeasuresConsistency.py b/product/ERP5/Constraint/ResourceMeasuresConsistency.py
new file mode 100644
index 0000000000..68c9e0ee90
--- /dev/null
+++ b/product/ERP5/Constraint/ResourceMeasuresConsistency.py
@@ -0,0 +1,115 @@
+##############################################################################
+#
+# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Products.ERP5Type.Constraint import Constraint
+
+class ResourceMeasuresConsistency(Constraint):
+  """Check that measures defined on a resource are not meaningless.
+
+  Choosing quantity units for a resource without defining measures is
+  tolerated, for compatibility, although conversion between units won't be
+  possible.
+  """
+
+  _message_id_list = ['message_measure_no_quantity_unit',
+                      'message_measure_no_quantity',
+                      'message_duplicate_metric_type',
+                      'message_duplicate_default_measure',
+                      'message_missing_metric_type']
+
+  _message_measure = "Measure for metric_type '${metric_type}' "
+  message_measure_no_quantity_unit = \
+    _message_measure + "doesn't have a valid quantity_unit"
+  message_measure_no_quantity = \
+    _message_measure + "doesn't have a valid quantity value"
+  message_duplicate_metric_type = \
+    "Several measures have the same metric_type '${metric_type}'"
+  message_duplicate_default_measure = \
+    "Several measures are associated to the same unit '${quantity_unit}'"
+  message_missing_metric_type = \
+    "Implicit measure for the management unit can't be created" \
+    " because 'metric_type/${metric_type}' category doesn't exist."
+
+  def checkConsistency(self, obj, fixit=0):
+    """Implement here the consistency checker
+    """
+    error_list = []
+    portal = obj.getPortalObject()
+
+    if obj.getPortalType() not in portal.getPortalResourceTypeList():
+      return error_list
+
+    error = lambda msg, **kw: error_list.append(
+      self._generateError(obj, self._getMessage(msg), mapping=kw))
+
+    getCategoryValue = portal.portal_categories.getCategoryValue
+    display = lambda *args, **kw: \
+      getCategoryValue(*args, **kw).getCompactLogicalPath()
+
+    top = lambda relative_url: relative_url.split('/', 1)[0]
+
+    quantity_map = {}
+    metric_type_set = set()
+
+    for measure in obj.getMeasureList():
+      metric_type = measure.getMetricType()
+      if metric_type:
+        quantity = top(metric_type)
+        default_or_generic = quantity_map.setdefault(quantity, [0, 0])
+        if measure.getDefaultMetricType():
+          default_or_generic[0] += 1
+        if quantity == metric_type:
+          default_or_generic[1] += 1
+
+        if not measure.getConvertedQuantityUnit():
+          error('message_measure_no_quantity_unit',
+                metric_type=display(metric_type, 'metric_type'))
+        elif not measure.asCatalogRowList():
+          error('message_measure_no_quantity',
+                metric_type=display(metric_type, 'metric_type'))
+        if metric_type in metric_type_set:
+          error('message_duplicate_metric_type',
+                metric_type=display(metric_type, 'metric_type'))
+        else:
+          metric_type_set.add(metric_type)
+      #else:
+      # pass # we don't care about undefined measures
+
+    for i, quantity_unit in enumerate(obj.getQuantityUnitList()):
+      quantity = top(quantity_unit)
+      default, generic = quantity_map.get(quantity, (0, 0))
+      if (default or generic) > 1:
+        error('message_duplicate_default_measure',
+              quantity_unit=display(quantity_unit, 'quantity_unit'))
+      elif not (default or generic):
+        if i:
+          pass # tolerate quantity units without any measure associated to them
+        else: # management unit: check we can create an implicit measure
+          if getCategoryValue(quantity, 'metric_type') is None:
+            error('message_missing_metric_type', metric_type=quantity)
+
+    return error_list
diff --git a/product/ERP5/Document/Amount.py b/product/ERP5/Document/Amount.py
index 428e0dee49..0f763b9cd1 100644
--- a/product/ERP5/Document/Amount.py
+++ b/product/ERP5/Document/Amount.py
@@ -405,17 +405,10 @@ class Amount(Base, Variated):
       Price is defined on 
       
     """
-    result = None
-    efficiency = self.getEfficiency()
-    if efficiency != 0:
-      resource_price = self.getResourcePrice()
-      if resource_price is not None:
-        return resource_price * self.getConvertedQuantity() / efficiency
-    price = self.getPrice()
-    quantity = self.getQuantity()
-    if type(price) in (type(1.0), type(1)) and type(quantity) in (type(1.0), type(1)):
-      result = quantity * price
-    return result
+    price = self.getResourcePrice()
+    quantity = self.getNetConvertedQuantity()
+    if isinstance(price, (int, float)) and isinstance(quantity, (int, float)):
+      return quantity * price
 
   # Conversion to standard unit
   security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedQuantity')
@@ -426,25 +419,26 @@ class Amount(Base, Variated):
     resource = self.getResourceValue()
     quantity_unit = self.getQuantityUnit()
     quantity = self.getQuantity()
-    converted_quantity = None
-    if resource is not None:
-      resource_quantity_unit = resource.getDefaultQuantityUnit()
-      converted_quantity = resource.convertQuantity(quantity, quantity_unit, resource_quantity_unit)
-    else:
-      #LOG("ERP5 WARNING:", 100, 'could not convert quantity for %s' % self.getRelativeUrl())
-      pass
-    return converted_quantity
+    if quantity is not None and quantity_unit and resource is not None:
+      converted = resource.convertQuantity(quantity, quantity_unit,
+                                           resource.getDefaultQuantityUnit(),
+                                           self.getVariationCategoryList())
+      # For compatibility, return quantity non-converted if conversion fails.
+      if converted is not None:
+        return converted
+    return quantity
 
   security.declareProtected(Permissions.ModifyPortalContent, 'setConvertedQuantity')
   def setConvertedQuantity(self, value):
     resource = self.getResourceValue()
     quantity_unit = self.getQuantityUnit()
-    if resource is not None:
-      resource_quantity_unit = resource.getDefaultQuantityUnit()
-      quantity = resource.convertQuantity(value, resource_quantity_unit, quantity_unit)
-      self.setQuantity(quantity)
-    else:
-      LOG("ERP5 WARNING:", 100, 'could not set converted quantity for %s' % self.getRelativeUrl())
+    if value is not None and quantity_unit and resource is not None:
+      quantity = resource.convertQuantity(value,
+                                          resource.getDefaultQuantityUnit(),
+                                          quantity_unit,
+                                          self.getVariationCategoryList())
+      if quantity is not None:
+        return self.setQuantity(quantity)
 
   security.declareProtected(Permissions.AccessContentsInformation, 'getNetQuantity')
   def getNetQuantity(self):
diff --git a/product/ERP5/Document/Currency.py b/product/ERP5/Document/Currency.py
index 8a8e577fa4..1dc59a1ced 100644
--- a/product/ERP5/Document/Currency.py
+++ b/product/ERP5/Document/Currency.py
@@ -63,7 +63,9 @@ class Currency(Resource):
 
   # Unit conversion
   security.declareProtected(Permissions.AccessContentsInformation, 'convertQuantity')
-  def convertQuantity(self, quantity, from_unit, to_unit):
+  def convertQuantity(self, quantity, from_unit, to_unit, variation_list=()):
+    # 'variation_list' parameter may be deprecated:
+    # cf Measure.getConvertedQuantity
     return quantity
 
   security.declareProtected(Permissions.AccessContentsInformation, 'convertCurrency')
diff --git a/product/ERP5/Document/Measure.py b/product/ERP5/Document/Measure.py
new file mode 100644
index 0000000000..136e5be661
--- /dev/null
+++ b/product/ERP5/Document/Measure.py
@@ -0,0 +1,285 @@
+##############################################################################
+#
+# Copyright (c) 2008 Nexedi SARL and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from AccessControl import ClassSecurityInfo
+
+from Products.ERP5Type import PropertySheet
+from Products.ERP5Type.Permissions import AccessContentsInformation
+from Products.ERP5Type.XMLMatrix import XMLMatrix
+from Products.ERP5.Variated import Variated
+
+class Measure(XMLMatrix):
+  """
+    A Measure
+  """
+
+  meta_type = 'ERP5 Measure'
+  portal_type = 'Measure'
+
+  # Declarative security
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(AccessContentsInformation)
+
+  # Declarative properties
+  property_sheets = ( PropertySheet.Base
+                    , PropertySheet.XMLObject
+                    , PropertySheet.CategoryCore
+                    , PropertySheet.Measure
+                    )
+
+  security.declareProtected(AccessContentsInformation, 'getResourceValue')
+  def getResourceValue(self):
+    """
+    Gets the resource object described by this measure.
+    """
+    return self.getDefaultResourceValue()
+
+  ##
+  #  Forms.
+
+  security.declareProtected(AccessContentsInformation, 'getVariationRangeCategoryItemList')
+  def getVariationRangeCategoryItemList(self, variation):
+    """
+    Returns possible variation category values for the selected variation.
+    variation is a 0-based index and possible category values is provided
+    as a list of tuples (id, title). This is mostly useful for matrixbox.
+    """
+    mvbc_list = self.getMeasureVariationBaseCategoryList()
+    if len(mvbc_list) <= variation:
+      return ()
+    return self.getResourceValue().getVariationCategoryItemList(
+      is_right_display=1,
+      base_category_list=(mvbc_list[variation],),
+      omit_individual_variation=0,
+      display_base_category=0,
+      sort_id='id')
+
+  security.declareProtected(AccessContentsInformation, 'getQuantityUnitItemList')
+  def getQuantityUnitItemList(self):
+    """
+    Returns the list of possible quantity units for the current metric type.
+    This is mostly useful in ERP5Form instances to generate selection menus.
+    """
+    metric_type = self.getMetricType()
+    if not metric_type:
+      return ('', ''),
+    portal = self.getPortalObject()
+    return getattr(
+      portal.portal_categories.getCategoryValue(metric_type.split('/', 1)[0],
+                                                'quantity_unit'),
+      portal.portal_preferences.getPreference(
+        'preferred_category_child_item_list_method_id',
+        'getCategoryChildCompactLogicalPathItemList')
+    )(recursive=0, local_sort_id='quantity', checked_permission='View')
+
+  security.declareProtected(AccessContentsInformation, 'getLocalQuantityUnit')
+  def getLocalQuantityUnit(self):
+    """
+    Returns the 'quantity_unit' category without acquisition.
+    Used in Resource_viewMeasure and Measure_view.
+    """
+    quantity_unit_list = self.getPortalObject().portal_categories \
+      .getSingleCategoryMembershipList(self, 'quantity_unit')
+    if quantity_unit_list:
+      return quantity_unit_list[0]
+
+  ##
+  #  Measures associated to a quantity unit of the resource
+  #  have a specific behaviour.
+
+  security.declareProtected(AccessContentsInformation, 'isDefaultMeasure')
+  def isDefaultMeasure(self, quantity_unit=None):
+    """
+    Checks if self is a default measure for the associated resource.
+    """
+    default = self.getResourceValue().getDefaultMeasure(quantity_unit)
+    return default is not None \
+       and self.getRelativeUrl() == default.getRelativeUrl()
+
+  ##
+  #  Conversion.
+
+  security.declareProtected(AccessContentsInformation, 'getConvertedQuantityUnit')
+  def getConvertedQuantityUnit(self):
+    """
+    Gets the quantity unit ratio, in respect to the base quantity unit.
+    """
+    quantity_unit = self.getQuantityUnitValue()
+    metric_type = self.getMetricType()
+    if quantity_unit is not None and metric_type and \
+        quantity_unit.getParentId() == metric_type.split('/', 1)[0]:
+      return quantity_unit.getProperty('quantity')
+
+  security.declareProtected(AccessContentsInformation, 'getConvertedQuantity')
+  def getConvertedQuantity(self, variation_list=()):
+    """
+    Gets the measure value for a specified variation,
+    in respected to the base quantity unit.
+
+    Should it be reimplemented using predicates?
+    If so, 'variation_list' parameter is deprecated.
+    """
+    quantity_unit = self.getConvertedQuantityUnit()
+    if not quantity_unit:
+      return
+    quantity = self.getQuantity()
+    if variation_list:
+      variation_set = set(variation_list)
+      for cell in self.objectValues():
+        # if cell.test(context): # XXX
+        if variation_set.issuperset(
+            cell.getMembershipCriterionCategoryList()):
+          quantity = cell.getQuantity()
+          break
+    return quantity * quantity_unit
+
+  ##
+  #  Cataloging.
+
+  security.declareProtected(AccessContentsInformation, 'asCatalogRowList')
+  def asCatalogRowList(self):
+    """
+    Returns the list of rows to insert in the measure table of the catalog.
+    Called by Resource.getMeasureRowList.
+    """
+    quantity_unit = self.getConvertedQuantityUnit()
+    if not quantity_unit:
+      return ()
+    uid = self.getUid()
+    resource = self.getResourceValue()
+    resource_uid = resource.getUid()
+    metric_type_uid = self.getMetricTypeUid()
+    quantity = self.getQuantity()
+
+    # The only purpose of the defining a default measure explicitly is to
+    # set a specific metric_type for the management unit.
+    # Therefore, the measure mustn't be variated and the described quantity
+    # (quantity * quantity_unit) must match the management unit.
+    # If the conditions aren't met, return an empty list.
+    default = self.isDefaultMeasure()
+
+    measure_variation_base_category_list = \
+      self.getMeasureVariationBaseCategoryList()
+    if not measure_variation_base_category_list:
+      # Easy case: there is no variation axe for this metric_type,
+      # so we simply return 1 row.
+      if quantity is not None:
+        quantity *= quantity_unit
+        if (not default or quantity ==
+            resource.getQuantityUnitValue().getProperty('quantity')):
+          return (uid, resource_uid, '^', metric_type_uid, quantity),
+      return ()
+
+    if default:
+      return ()
+
+    # 1st step: Build a list of possible variation combinations.
+    # Each element of the list (variation_list) is a pair of lists, where:
+    #  * first list's elements are regex tokens:
+    #    they'll be used to build the 'variation' values (in the result).
+    #  * the second list is a combination of categories, used to find
+    #    the measure cells containing the 'quantity' values.
+    #
+    # This step is done by starting from a 1-element list (variation_list).
+    # For each variation axe (if variation_base_category in
+    # measure_variation_base_category_list), we rebuild variation_list entirely
+    # and its size is multiplied by the number of categories in this axe.
+    # For other varation base categories (variation_base_category not in
+    # measure_variation_base_category_list), we simply
+    # update variation_list to add 1 regex token to each regex list.
+    #
+    # Example:
+    #  * variation base categories: colour, logo, size
+    #  * variation axes: colour, size
+    #
+    #  variation_list (tokens are simplified for readability):
+    # 0. []
+    # 1. [([colour/red],   ['colour/red']),
+    #     ([colour/green], ['colour/green']),
+    #     ([colour/blue],  ['colour/blue'])]
+    # 2. [([colour/red,   logo/*], ['colour/red']),
+    #     ([colour/green, logo/*], ['colour/green']),
+    #     ([colour/blue,  logo/*], ['colour/blue'])]
+    # 3. [([colour/red,   logo/*, size/small], ['colour/red',   'size/small']),
+    #     ([colour/green, logo/*, size/small], ['colour/green', 'size/small']),
+    #     ([colour/blue,  logo/*, size/small], ['colour/blue',  'size/small']),
+    #     ([colour/red,   logo/*, size/medium], ['colour/red',   'size/medium']),
+    #     ([colour/green, logo/*, size/medium], ['colour/green', 'size/medium']),
+    #     ([colour/blue,  logo/*, size/medium], ['colour/blue',  'size/medium']),
+    #     ([colour/red,   logo/*, size/big], ['colour/red',   'size/big']),
+    #     ([colour/green, logo/*, size/big], ['colour/green', 'size/big']),
+    #     ([colour/blue,  logo/*, size/big], ['colour/blue',  'size/big'])]
+
+    # Note that from this point, we always work with sorted lists of
+    # categories (or regex tokens).
+
+    variation_list = ([], []),
+    optional_variation_base_category_set = \
+      set(resource.getOptionalVariationBaseCategoryList())
+    for variation_base_category in sorted(
+        resource.getVariationBaseCategoryList(omit_optional_variation=0)):
+      if variation_base_category in measure_variation_base_category_list:
+        # This is where we rebuild variation_list entirely. Size of
+        # variation_list is multiplied by len(getVariationCategoryList).
+        # The lists of each pairs in variation_list get one more element:
+        # variation_category.
+        variation_list = [(regex_list + [variation_category + '\n'],
+                           variation_base_category_list + [variation_category])
+          for variation_category in resource.getVariationCategoryList(
+            base_category_list=(variation_base_category,),
+            omit_individual_variation=0)
+          for regex_list, variation_base_category_list in variation_list]
+      else:
+        variation_base_category_regex = variation_base_category + '/[^\n]+\n'
+        if variation_base_category in optional_variation_base_category_set:
+          variation_base_category_regex = \
+            '(%s)*' % (variation_base_category_regex, )
+        for regex_list, variation_base_category_list in variation_list:
+          regex_list.append(variation_base_category_regex)
+
+    # 2nd step: Retrieve all measure cells in a dictionary for fast lookup.
+    cell_map = {}
+    for cell in self.objectValues():
+      cell_map[tuple(sorted(cell.getMembershipCriterionCategoryList()))] \
+        = cell.getQuantity()
+
+    # 3rd step: Build the list of rows to return,
+    # by merging variation_list (1st step) and cell_map (2nd step).
+    row_list = []
+    for regex_list, variation_base_category_list in variation_list:
+      cell = cell_map.get(tuple(variation_base_category_list))
+      if cell is None:
+        if quantity is None:
+          continue
+        cell = quantity
+      row_list.append((uid,
+                       resource_uid,
+                       '^%s$' % ''.join(regex_list),
+                       metric_type_uid,
+                       cell * quantity_unit))
+
+    return row_list
diff --git a/product/ERP5/Document/Movement.py b/product/ERP5/Document/Movement.py
index e42ed4c5e3..6ff6c5c057 100644
--- a/product/ERP5/Document/Movement.py
+++ b/product/ERP5/Document/Movement.py
@@ -199,9 +199,18 @@ class Movement(XMLObject, Amount):
   # _getPrice is defined in the order / delivery
   # Pricing mehod
   def _getPrice(self, context):
+    context = self.asContext(context=context,
+                             quantity=self.getConvertedQuantity())
     operand_dict = self.getPriceCalculationOperandDict(context=context)
     if operand_dict is not None:
-      return operand_dict['price']
+      price = operand_dict['price']
+      resource = self.getResourceValue()
+      quantity_unit = self.getQuantityUnit()
+      if price is not None and quantity_unit and resource is not None:
+        return resource.convertQuantity(price, quantity_unit,
+                                        resource.getDefaultQuantityUnit(),
+                                        self.getVariationCategoryList())
+      return price
 
   def _getTotalPrice(self, default=None, context=None, fast=0):
     price = self.getPrice(context=context)
diff --git a/product/ERP5/Document/Resource.py b/product/ERP5/Document/Resource.py
index 66d390de8e..b72ff7b06a 100644
--- a/product/ERP5/Document/Resource.py
+++ b/product/ERP5/Document/Resource.py
@@ -252,11 +252,6 @@ class Resource(XMLMatrix, Variated):
                     omit_individual_variation=omit_individual_variation,**kw)
       return [x[1] for x in vcil]
 
-    # Unit conversion
-    security.declareProtected(Permissions.AccessContentsInformation, 'convertQuantity')
-    def convertQuantity(self, quantity, from_unit, to_unit):
-      return quantity
-
 # This patch is temporary and allows to circumvent name conflict in ZSQLCatalog process for Coramy
     security.declareProtected(Permissions.AccessContentsInformation,
                                               'getDefaultDestinationAmountBis')
@@ -783,3 +778,120 @@ class Resource(XMLMatrix, Variated):
       except TypeError:
         return 0
       return 0
+
+
+    def _getConversionRatio(self, quantity_unit, variation_list):
+      """
+      Converts a quantity unit into a ratio in respect to the resource's
+      management unit, for the specified variation.
+      A quantity can be multiplied by the returned value in order to convert it
+      in the management unit.
+
+      'variation_list' parameter may be deprecated:
+      cf Measure.getConvertedQuantity
+      """
+      management_unit = self.getDefaultQuantityUnit()
+      if management_unit == quantity_unit:
+        return 1.0
+      traverse = self.portal_categories['quantity_unit'].unrestrictedTraverse
+      quantity = traverse(quantity_unit).getProperty('quantity')
+      if quantity_unit.split('/', 1)[0] != management_unit.split('/', 1)[0]:
+        measure = self.getDefaultMeasure(quantity_unit)
+        quantity /= measure.getConvertedQuantity(variation_list)
+      else:
+        quantity /= traverse(management_unit).getProperty('quantity')
+      return quantity
+
+    # Unit conversion
+    security.declareProtected(Permissions.AccessContentsInformation, 'convertQuantity')
+    def convertQuantity(self, quantity, from_unit, to_unit, variation_list=()):
+      # 'variation_list' parameter may be deprecated:
+      # cf Measure.getConvertedQuantity
+      try:
+        return quantity * self._getConversionRatio(from_unit, variation_list) \
+                        / self._getConversionRatio(to_unit, variation_list)
+      except (ArithmeticError, AttributeError, LookupError, TypeError), error:
+        # For compatibility, we only log the error and return None.
+        # No exception for the moment.
+        LOG('Resource.convertQuantity', WARNING,
+            'could not convert quantity for %s (%r)'
+            % (self.getRelativeUrl(), error))
+
+    security.declareProtected(Permissions.AccessContentsInformation,
+                              'getMeasureList')
+    def getMeasureList(self):
+      """
+      Gets the list of Measure objects describing this resource.
+      """
+      return self.objectValues(portal_type='Measure')
+
+    security.declareProtected(Permissions.AccessContentsInformation,
+                              'getDefaultMeasure')
+    def getDefaultMeasure(self, quantity_unit=None):
+      """
+      Returns the measure object associated to quantity_unit.
+      If no quantity_unit is specified, the quantity_unit of the resource is used.
+      None is returned if the number of found measures differs from 1.
+      """
+      if quantity_unit is None:
+        quantity_unit = self.getQuantityUnit()
+      if quantity_unit:
+        top = lambda relative_url: relative_url.split('/', 1)[0]
+
+        quantity = top(quantity_unit)
+        generic = []
+        default = []
+        for measure in self.getMeasureList():
+          metric_type = measure.getMetricType()
+          if metric_type and quantity == top(metric_type) and \
+             measure.getDefaultMetricType():
+            default.append(measure)
+          if quantity == metric_type:
+            generic.append(measure)
+        result = default or generic
+        if len(result) == 1:
+          return result[0]
+
+    security.declareProtected(Permissions.AccessContentsInformation,
+                              'getMeasureRowList')
+    def getMeasureRowList(self):
+      """
+      Returns a list rows to insert in the measure table.
+      Used by z_catalog_measure_list.
+      """
+      quantity_unit_value = self.getQuantityUnitValue()
+      if quantity_unit_value is None:
+        return ()
+
+      quantity_unit = quantity_unit_value.getCategoryRelativeUrl()
+      default = self.getDefaultMeasure(quantity_unit)
+      if default is not None:
+        default = default.getRelativeUrl()
+      metric_type_map = {} # duplicate metric_type are not valid
+
+      for measure in self.getMeasureList():
+        metric_type = measure.getMetricType()
+        if metric_type in metric_type_map:
+          metric_type_map[metric_type] = ()
+        else:
+          metric_type_map[metric_type] = measure.asCatalogRowList()
+        if measure.getRelativeUrl() == default:
+          quantity_unit = ''
+
+      insert_list = []
+      for measure_list in metric_type_map.itervalues():
+        insert_list += measure_list
+
+      metric_type = quantity_unit.split('/', 1)[0]
+      if metric_type and metric_type not in metric_type_map:
+        # At this point, we know there is no default measure and we must add
+        # a row for the management unit, with the resource's uid as uid, and
+        # a generic metric_type.
+        quantity = quantity_unit_value.getProperty('quantity')
+        metric_type_uid = self.getPortalObject().portal_categories \
+                              .getCategoryUid(metric_type, 'metric_type')
+        if quantity and metric_type_uid:
+          uid = self.getUid()
+          insert_list += (uid, uid, '^', metric_type_uid, quantity),
+
+      return insert_list
diff --git a/product/ERP5/PropertySheet/Measure.py b/product/ERP5/PropertySheet/Measure.py
new file mode 100644
index 0000000000..0c6122d3b4
--- /dev/null
+++ b/product/ERP5/PropertySheet/Measure.py
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2008 Nexedi SARL and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+class Measure:
+
+  _properties = (
+    { 'id'          : 'quantity',
+      'description' : "Value of the measure, expressed in the selected quantity unit.",
+      'type'        : 'float',
+      'mode'        : 'w' },
+    { 'id'          : 'measure_variation_base_category',
+      'description' : "Base category range of matrix.",
+      'type'        : 'tokens',
+      'mode'        : 'w' },
+    { 'id'          : 'default_metric_type',
+      'description' : "Use this measure by default to perform unit conversion\n"
+                      "(useful in cases where only a quantity unit is specified).",
+      'type'        : 'boolean',
+      'mode'        : 'w' },
+   )
+
+  _categories = ( 'metric_type', 'quantity_unit' )
diff --git a/product/ERP5/PropertySheet/Resource.py b/product/ERP5/PropertySheet/Resource.py
index 0c032e7b38..c1155857d7 100644
--- a/product/ERP5/PropertySheet/Resource.py
+++ b/product/ERP5/PropertySheet/Resource.py
@@ -179,6 +179,13 @@ class Resource:
 
     )
 
+    _constraints = (
+        {   'id': 'resource_measures_consistency',
+            'description': '',
+            'type': 'ResourceMeasuresConsistency',
+        },
+    )
+
     _categories = ( 'source', 'destination', 'quantity_unit', 'price_unit',
                     'weight_unit', 'length_unit', 'height_unit', 'width_unit',
                     'volume_unit',
diff --git a/product/ERP5/Tool/SimulationTool.py b/product/ERP5/Tool/SimulationTool.py
index e97318846d..5a41e1dc14 100644
--- a/product/ERP5/Tool/SimulationTool.py
+++ b/product/ERP5/Tool/SimulationTool.py
@@ -49,6 +49,7 @@ from Products.PythonScripts.Utility import allow_class
 from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery, QueryMixin
 
 from Shared.DC.ZRDB.Results import Results
+from Products.ERP5Type.Utils import mergeZRDBResults
 
 class SimulationTool(BaseTool):
     """
@@ -878,7 +879,8 @@ class SimulationTool(BaseTool):
                          default_stock_table='stock',
                          selection_domain=None, selection_report=None,
                          statistic=0, inventory_list=1, 
-                         precision=None, connection_id=None, **kw):
+                         precision=None, connection_id=None,
+                         quantity_unit=None, **kw):
       """
         Returns a list of inventories for a single or multiple
         resources on a single or multiple nodes, grouped by resource,
@@ -1058,6 +1060,7 @@ class SimulationTool(BaseTool):
               assert isinstance(where_query, basestring) and len(where_query)
               stock_sql_kw['where_expression'] = '(%s) AND (%s)' % \
                 (where_query, greater_than_date_query)
+              LOG(None, 0, 'optimisation_success = True')
               # Get initial inventory amount
               initial_inventory_line_list = self.Resource_zGetInventoryList(
                 stock_table_id=EQUAL_DATE_TABLE_ID,
@@ -1066,7 +1069,8 @@ class SimulationTool(BaseTool):
                 selection_domain=selection_domain,
                 selection_report=selection_report, precision=precision,
                 inventory_list=inventory_list,
-                statistic=statistic, **inventory_stock_sql_kw)
+                statistic=statistic, quantity_unit=quantity_unit,
+                **inventory_stock_sql_kw)
               # Get delta inventory
               delta_inventory_line_list = self.Resource_zGetInventoryList(
                 stock_table_id=GREATER_THAN_DATE_TABLE_ID,
@@ -1075,7 +1079,8 @@ class SimulationTool(BaseTool):
                 selection_domain=selection_domain,
                 selection_report=selection_report, precision=precision,
                 inventory_list=inventory_list,
-                statistic=statistic, **stock_sql_kw)
+                statistic=statistic, quantity_unit=quantity_unit,
+                **stock_sql_kw)
               # Match & add initial and delta inventories
               if src__:
                 sql_source_list.extend((initial_inventory_line_list,
@@ -1104,6 +1109,8 @@ class SimulationTool(BaseTool):
                 result_column_id_dict['inventory'] = None
                 result_column_id_dict['total_quantity'] = None
                 result_column_id_dict['total_price'] = None
+                if quantity_unit:
+                    result_column_id_dict['converted_quantity'] = None
                 def addLineValues(line_a=None, line_b=None):
                   """
                     Addition columns of 2 lines and return a line with same
@@ -1189,13 +1196,73 @@ class SimulationTool(BaseTool):
                     selection_domain=selection_domain,
                     selection_report=selection_report, precision=precision,
                     inventory_list=inventory_list, connection_id=connection_id,
-                    statistic=statistic, **stock_sql_kw)
+                    statistic=statistic, quantity_unit=quantity_unit,
+                    **stock_sql_kw)
         if src__:
           sql_source_list.append(result)
       if src__:
         result = ';\n-- NEXT QUERY\n'.join(sql_source_list)
       return result
 
+    security.declareProtected(Permissions.AccessContentsInformation,
+                              'getConvertedInventoryList')
+    def getConvertedInventoryList(self, metric_type, quantity_unit=1,
+                                  simulation_period='', **kw):
+      """
+      Return list of inventory with a 'converted_quantity' additional column,
+      which contains the sum of measurements for the specified metric type,
+      expressed in the 'quantity_unit' unit.
+
+      metric_type   - category relative url
+      quantity_unit - int, float or category relative url
+      """
+      getCategory = self.getPortalObject().portal_categories.getCategoryValue
+
+      kw['metric_type_uid'] = Query(
+        metric_type_uid=getCategory(metric_type, 'metric_type').getUid(),
+        table_alias_list=(("measure", "measure"),))
+
+      if isinstance(quantity_unit, str):
+        quantity_unit = getCategory(quantity_unit,
+                                   'quantity_unit').getProperty('quantity')
+
+      method = getattr(self,'get%sInventoryList' % simulation_period)
+      return method(quantity_unit=quantity_unit, **kw)
+
+    security.declareProtected(Permissions.AccessContentsInformation,
+                              'getAllInventoryList')
+    def getAllInventoryList(self, src__=0, **kw):
+      """
+      Returns list of inventory, for all periods.
+      Performs 1 SQL request for each simulation state, and merge the results.
+      Rename relevant columns with a '${simulation}_' prefix
+      (ex: 'total_price' -> 'current_total_price').
+      """
+      columns = ('total_quantity', 'total_price', 'converted_quantity')
+
+      # Guess the columns to use to identify each row, by looking at the GROUP
+      # clause. Note that the call to 'mergeZRDBResults' will crash if the GROUP
+      # clause contains a column not requested in the SELECT clause.
+      kw.update(self._getDefaultGroupByParameters(**kw), ignore_group_by=1)
+      group_by_list = self._generateKeywordDict(**kw)[1].get('group_by', ())
+
+      results = []
+      edit_result = {}
+      get_false_value = lambda row, column_name: row.get(column_name) or 0
+
+      for simulation in 'current', 'available', 'future':
+        method = getattr(self, 'get%sInventoryList' % simulation.capitalize())
+        rename = {'inventory': None} # inventory column is deprecated
+        for column in columns:
+          rename[column] = new_name = '%s_%s' % (simulation, column)
+          edit_result[new_name] = get_false_value
+        results += (method(src__=src__, **kw), rename),
+
+      if src__:
+        return ';\n-- NEXT QUERY\n'.join(r[0] for r in results)
+      return mergeZRDBResults(results, group_by_list, edit_result)
+
+
     security.declareProtected(Permissions.AccessContentsInformation,
                               'getCurrentInventoryList')
     def getCurrentInventoryList(self, omit_transit=1, 
@@ -1268,7 +1335,7 @@ class SimulationTool(BaseTool):
                               'getAvailableInventoryStat')
     def getAvailableInventoryStat(self, **kw):
       """
-      Returns statistics of current inventory grouped by section or site
+      Returns statistics of available inventory grouped by section or site
       """
       return self.getInventoryStat(simulation_period='Available', **kw)
 
diff --git a/product/ERP5/bootstrap/erp5_core/CategoryTemplateItem/portal_categories/quantity_unit.xml b/product/ERP5/bootstrap/erp5_core/CategoryTemplateItem/portal_categories/quantity_unit.xml
index f096f8e2ba..6ceee8f311 100644
--- a/product/ERP5/bootstrap/erp5_core/CategoryTemplateItem/portal_categories/quantity_unit.xml
+++ b/product/ERP5/bootstrap/erp5_core/CategoryTemplateItem/portal_categories/quantity_unit.xml
@@ -45,9 +45,9 @@
             <value>
               <tuple>
                 <string>delivery</string>
-                <string>resource</string>
                 <string>order</string>
                 <string>parent</string>
+                <string>resource</string>
               </tuple>
             </value>
         </item>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view.xml
index fc87c760f2..1f90ad748b 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view.xml
@@ -121,6 +121,7 @@
                         <string>my_codification</string>
                         <string>my_int_index</string>
                         <string>my_translated_validation_state_title</string>
+                        <string>my_quantity</string>
                       </list>
                     </value>
                 </item>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view/my_quantity.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view/my_quantity.xml
new file mode 100644
index 0000000000..5fa115fdde
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Category_view/my_quantity.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>display_width</string>
+                <string>precision</string>
+                <string>enabled</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_quantity</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>display_width</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>precision</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>display_width</string> </key>
+                    <value> <int>20</int> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_quantity</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>precision</string> </key>
+                    <value> <int>15</int> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: max(15,int(field.getTemplateField().get_value(\'display_width\')))</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <tuple>
+        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>python: (lambda x: x.getPortalType() == \'Base Category\' and x.getId() == \'quantity_unit\')(here.getParent().getParent())</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetInventoryList.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetInventoryList.xml
index 97cc8bd955..9097a21442 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetInventoryList.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetInventoryList.xml
@@ -118,6 +118,12 @@
                                   <dictionary/>
                                 </value>
                             </item>
+                            <item>
+                                <key> <string>quantity_unit</string> </key>
+                                <value>
+                                  <dictionary/>
+                                </value>
+                            </item>
                             <item>
                                 <key> <string>section_filtered</string> </key>
                                 <value>
@@ -189,6 +195,7 @@
 <string>precision</string>
 <string>inventory_list</string>
 <string>statistic</string>
+<string>quantity_unit</string>
 <string>stock_table_id</string>
                           </list>
                         </value>
@@ -198,6 +205,12 @@
               </object>
             </value>
         </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
         <item>
             <key> <string>allow_simple_one_argument_traversal</string> </key>
             <value>
@@ -223,6 +236,7 @@ output_simulation_state:list\r\n
 precision\r\n
 inventory_list\r\n
 statistic\r\n
+quantity_unit\r\n
 stock_table_id=stock</string> </value>
         </item>
         <item>
@@ -267,10 +281,18 @@ SELECT\n
 <dtml-if expr="precision is not None">\n
   SUM(ROUND(<dtml-var stock_table_id>.quantity, <dtml-var precision>)) AS inventory,\n
   SUM(ROUND(<dtml-var stock_table_id>.quantity, <dtml-var precision>)) AS total_quantity,\n
+<dtml-if quantity_unit>\n
+  SUM(ROUND(<dtml-var stock_table_id>.quantity * measure.quantity, <dtml-var precision>))\n
+  / <dtml-sqlvar quantity_unit type=float> AS converted_quantity,\n
+</dtml-if>\n
   SUM(ROUND(<dtml-var stock_table_id>.total_price, <dtml-var precision>)) AS total_price\n
 <dtml-else>\n
   SUM(<dtml-var stock_table_id>.quantity) AS inventory,\n
   SUM(<dtml-var stock_table_id>.quantity) AS total_quantity,\n
+<dtml-if quantity_unit>\n
+  ROUND(SUM(<dtml-var stock_table_id>.quantity * measure.quantity)\n
+        / <dtml-sqlvar quantity_unit type=float>, 12) AS converted_quantity,\n
+</dtml-if>\n
   SUM(<dtml-var stock_table_id>.total_price) AS total_price\n
 </dtml-if>\n
 <dtml-if inventory_list>\n
@@ -340,6 +362,12 @@ WHERE\n
 <dtml-if selection_report>\n
   AND <dtml-var "portal_selections.buildSQLExpressionFromDomainSelection(selection_report, strict_membership=1)">\n
 </dtml-if>\n
+\n
+<dtml-if quantity_unit>\n
+  AND concat(<dtml-var stock_table_id>.variation_text,\'\\n\') REGEXP measure.variation\n
+</dtml-if>\n
+\n
+\n
 <dtml-if group_by_expression>\n
 GROUP BY\n
     <dtml-var group_by_expression>\n
@@ -392,10 +420,18 @@ SELECT\n
 <dtml-if expr="precision is not None">\n
   SUM(ROUND(<dtml-var stock_table_id>.quantity, <dtml-var precision>)) AS inventory,\n
   SUM(ROUND(<dtml-var stock_table_id>.quantity, <dtml-var precision>)) AS total_quantity,\n
+<dtml-if quantity_unit>\n
+  SUM(ROUND(<dtml-var stock_table_id>.quantity * measure.quantity, <dtml-var precision>))\n
+  / <dtml-sqlvar quantity_unit type=float> AS converted_quantity,\n
+</dtml-if>\n
   SUM(ROUND(<dtml-var stock_table_id>.total_price, <dtml-var precision>)) AS total_price\n
 <dtml-else>\n
   SUM(<dtml-var stock_table_id>.quantity) AS inventory,\n
   SUM(<dtml-var stock_table_id>.quantity) AS total_quantity,\n
+<dtml-if quantity_unit>\n
+  ROUND(SUM(<dtml-var stock_table_id>.quantity * measure.quantity)\n
+        / <dtml-sqlvar quantity_unit type=float>, 12) AS converted_quantity,\n
+</dtml-if>\n
   SUM(<dtml-var stock_table_id>.total_price) AS total_price\n
 </dtml-if>\n
 <dtml-if inventory_list>\n
@@ -465,6 +501,12 @@ WHERE\n
 <dtml-if selection_report>\n
   AND <dtml-var "portal_selections.buildSQLExpressionFromDomainSelection(selection_report, strict_membership=1)">\n
 </dtml-if>\n
+\n
+<dtml-if quantity_unit>\n
+  AND concat(<dtml-var stock_table_id>.variation_text,\'\\n\') REGEXP measure.variation\n
+</dtml-if>\n
+\n
+\n
 <dtml-if group_by_expression>\n
 GROUP BY\n
     <dtml-var group_by_expression>\n
diff --git a/product/ERP5/bootstrap/erp5_core/bt/revision b/product/ERP5/bootstrap/erp5_core/bt/revision
index 189296e610..779a8736e2 100644
--- a/product/ERP5/bootstrap/erp5_core/bt/revision
+++ b/product/ERP5/bootstrap/erp5_core/bt/revision
@@ -1 +1 @@
-825
\ No newline at end of file
+826
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.catalog_keys.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.catalog_keys.xml
new file mode 100644
index 0000000000..baf9e92bd9
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.catalog_keys.xml
@@ -0,0 +1,5 @@
+<catalog_method>
+ <item key="sql_clear_catalog" type="int">
+  <value>1</value>
+ </item>
+</catalog_method>
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.xml
new file mode 100644
index 0000000000..f005c6cdc0
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_drop_measure.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="SQL" module="Products.ZSQLMethods.SQL"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_arg</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="Args" module="Shared.DC.ZRDB.Aqueduct"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_data</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>_keys</string> </key>
+                        <value>
+                          <list/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>arguments_src</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>connection_id</string> </key>
+            <value> <string>erp5_sql_connection</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>z0_drop_measure</string> </value>
+        </item>
+        <item>
+            <key> <string>src</string> </key>
+            <value> <string>DROP TABLE IF EXISTS measure</string> </value>
+        </item>
+        <item>
+            <key> <string>template</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="__newobj__" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="SQL" module="Shared.DC.ZRDB.DA"/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>__name__</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<string>
+
+]]></string> </value>
+                    </item>
+                    <item>
+                        <key> <string>_vars</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>globals</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>raw</string> </key>
+                        <value> <string>DROP TABLE IF EXISTS measure</string> </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.catalog_keys.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.catalog_keys.xml
new file mode 100644
index 0000000000..d58ef064ea
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.catalog_keys.xml
@@ -0,0 +1,5 @@
+<catalog_method>
+ <item key="sql_uncatalog_object" type="int">
+  <value>1</value>
+ </item>
+</catalog_method>
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.xml
new file mode 100644
index 0000000000..32507633c0
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z0_uncatalog_measure.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="SQL" module="Products.ZSQLMethods.SQL"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_arg</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="Args" module="Shared.DC.ZRDB.Aqueduct"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_data</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>uid</string> </key>
+                                <value>
+                                  <dictionary/>
+                                </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>_keys</string> </key>
+                        <value>
+                          <list>
+<string>uid</string>
+                          </list>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>allow_simple_one_argument_traversal</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>arguments_src</string> </key>
+            <value> <string>uid</string> </value>
+        </item>
+        <item>
+            <key> <string>cache_time_</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>class_file_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>class_name_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>connection_hook</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>connection_id</string> </key>
+            <value> <string>erp5_sql_connection</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>z0_uncatalog_measure</string> </value>
+        </item>
+        <item>
+            <key> <string>max_cache_</string> </key>
+            <value> <int>100</int> </value>
+        </item>
+        <item>
+            <key> <string>max_rows_</string> </key>
+            <value> <int>1000</int> </value>
+        </item>
+        <item>
+            <key> <string>src</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<dtml-comment>\n
+  JM: Since unindexing a measure triggers the reindexing of the related\n
+  resource (what will clean the measure table - cf z0_catalog_measure_list),\n
+  is it required to delete according to uid column?\n
+  The test against metric_type_uid is there in case we delete a metric_type_uid\n
+  category that is used as an implicit measure.\n
+</dtml-comment>\n
+DELETE FROM measure\n
+WHERE <dtml-sqltest uid op=eq type=int>\n
+   OR <dtml-sqltest uid op=eq type=int column="metric_type_uid">\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>template</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="__newobj__" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="SQL" module="Shared.DC.ZRDB.DA"/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>__name__</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<string>
+
+]]></string> </value>
+                    </item>
+                    <item>
+                        <key> <string>_vars</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>globals</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>raw</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<dtml-comment>\n
+  JM: Since unindexing a measure triggers the reindexing of the related\n
+  resource (what will clean the measure table - cf z0_catalog_measure_list),\n
+  is it required to delete according to uid column?\n
+  The test against metric_type_uid is there in case we delete a metric_type_uid\n
+  category that is used as an implicit measure.\n
+</dtml-comment>\n
+DELETE FROM measure\n
+WHERE <dtml-sqltest uid op=eq type=int>\n
+   OR <dtml-sqltest uid op=eq type=int column="metric_type_uid">\n
+
+
+]]></string> </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.catalog_keys.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.catalog_keys.xml
new file mode 100644
index 0000000000..e87180826b
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.catalog_keys.xml
@@ -0,0 +1,13 @@
+<catalog_method>
+ <item key="sql_catalog_object_list" type="int">
+  <value>1</value>
+ </item>
+ <item key="_is_filtered_archive" type="int">
+  <value>1</value>
+ </item>
+ <item key="_filter_expression_archive" type="str">
+  <value>python: here.getPortalType() in here.getPortalResourceTypeList()</value>
+ </item>
+ <item key="_filter_type_archive" type="tuple">
+ </item>
+</catalog_method>
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.xml
new file mode 100644
index 0000000000..2392c8317f
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_catalog_measure_list.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="SQL" module="Products.ZSQLMethods.SQL"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_arg</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="Args" module="Shared.DC.ZRDB.Aqueduct"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_data</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>getMeasureRowList</string> </key>
+                                <value>
+                                  <dictionary/>
+                                </value>
+                            </item>
+                            <item>
+                                <key> <string>uid</string> </key>
+                                <value>
+                                  <dictionary/>
+                                </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>_keys</string> </key>
+                        <value>
+                          <list>
+<string>uid</string>
+<string>getMeasureRowList</string>
+                          </list>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>allow_simple_one_argument_traversal</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>arguments_src</string> </key>
+            <value> <string>uid\n
+getMeasureRowList</string> </value>
+        </item>
+        <item>
+            <key> <string>cache_time_</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>class_file_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>class_name_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>connection_hook</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>connection_id</string> </key>
+            <value> <string>erp5_sql_connection</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>z_catalog_measure_list</string> </value>
+        </item>
+        <item>
+            <key> <string>max_cache_</string> </key>
+            <value> <int>100</int> </value>
+        </item>
+        <item>
+            <key> <string>max_rows_</string> </key>
+            <value> <int>1000</int> </value>
+        </item>
+        <item>
+            <key> <string>src</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+DELETE FROM `measure` WHERE\n
+  <dtml-sqltest uid column="resource_uid" type="int" multiple>;\n
+\n
+<dtml-let measure_list="[]">\n
+  <dtml-in getMeasureRowList prefix="loop">\n
+    <dtml-call expr="loop_item and measure_list.extend(loop_item)">\n
+  </dtml-in>\n
+\n
+  <dtml-if measure_list>\n
+    <dtml-var sql_delimiter>\n
+\n
+INSERT INTO `measure`\n
+VALUES\n
+    <dtml-in measure_list prefix="loop">\n
+(\n
+  <dtml-sqlvar expr="loop_item[0]" type="int">,\n
+  <dtml-sqlvar expr="loop_item[1]" type="int">,\n
+  <dtml-sqlvar expr="loop_item[2]" type="string">,\n
+  <dtml-sqlvar expr="loop_item[3]" type="int">,\n
+  <dtml-sqlvar expr="loop_item[4]" type="float">\n
+)\n
+<dtml-unless sequence-end>,</dtml-unless>\n
+    </dtml-in>\n
+\n
+  </dtml-if>\n
+</dtml-let>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>template</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="__newobj__" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="SQL" module="Shared.DC.ZRDB.DA"/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>__name__</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<string>
+
+]]></string> </value>
+                    </item>
+                    <item>
+                        <key> <string>_vars</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>globals</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>raw</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+DELETE FROM `measure` WHERE\n
+  <dtml-sqltest uid column="resource_uid" type="int" multiple>;\n
+\n
+<dtml-let measure_list="[]">\n
+  <dtml-in getMeasureRowList prefix="loop">\n
+    <dtml-call expr="loop_item and measure_list.extend(loop_item)">\n
+  </dtml-in>\n
+\n
+  <dtml-if measure_list>\n
+    <dtml-var sql_delimiter>\n
+\n
+INSERT INTO `measure`\n
+VALUES\n
+    <dtml-in measure_list prefix="loop">\n
+(\n
+  <dtml-sqlvar expr="loop_item[0]" type="int">,\n
+  <dtml-sqlvar expr="loop_item[1]" type="int">,\n
+  <dtml-sqlvar expr="loop_item[2]" type="string">,\n
+  <dtml-sqlvar expr="loop_item[3]" type="int">,\n
+  <dtml-sqlvar expr="loop_item[4]" type="float">\n
+)\n
+<dtml-unless sequence-end>,</dtml-unless>\n
+    </dtml-in>\n
+\n
+  </dtml-if>\n
+</dtml-let>\n
+
+
+]]></string> </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.catalog_keys.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.catalog_keys.xml
new file mode 100644
index 0000000000..baf9e92bd9
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.catalog_keys.xml
@@ -0,0 +1,5 @@
+<catalog_method>
+ <item key="sql_clear_catalog" type="int">
+  <value>1</value>
+ </item>
+</catalog_method>
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.xml
new file mode 100644
index 0000000000..4ddb798a07
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_create_measure.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="SQL" module="Products.ZSQLMethods.SQL"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_arg</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="Args" module="Shared.DC.ZRDB.Aqueduct"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_data</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>_keys</string> </key>
+                        <value>
+                          <list/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>allow_simple_one_argument_traversal</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>arguments_src</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>cache_time_</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>class_file_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>class_name_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>connection_hook</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>connection_id</string> </key>
+            <value> <string>erp5_sql_connection</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>z_create_measure</string> </value>
+        </item>
+        <item>
+            <key> <string>max_cache_</string> </key>
+            <value> <int>100</int> </value>
+        </item>
+        <item>
+            <key> <string>max_rows_</string> </key>
+            <value> <int>1000</int> </value>
+        </item>
+        <item>
+            <key> <string>src</string> </key>
+            <value> <string>CREATE TABLE `measure` (\n
+  `uid` BIGINT UNSIGNED NOT NULL,\n
+  `resource_uid` BIGINT UNSIGNED NOT NULL,\n
+  `variation` VARCHAR(255),\n
+  `metric_type_uid` BIGINT UNSIGNED NOT NULL,\n
+  `quantity` REAL NOT NULL,\n
+  PRIMARY KEY (`uid`, `variation`),\n
+  KEY (`metric_type_uid`)\n
+) TYPE=InnoDB;\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>template</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="__newobj__" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="SQL" module="Shared.DC.ZRDB.DA"/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>__name__</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<string>
+
+]]></string> </value>
+                    </item>
+                    <item>
+                        <key> <string>_vars</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>globals</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>raw</string> </key>
+                        <value> <string>CREATE TABLE `measure` (\n
+  `uid` BIGINT UNSIGNED NOT NULL,\n
+  `resource_uid` BIGINT UNSIGNED NOT NULL,\n
+  `variation` VARCHAR(255),\n
+  `metric_type_uid` BIGINT UNSIGNED NOT NULL,\n
+  `quantity` REAL NOT NULL,\n
+  PRIMARY KEY (`uid`, `variation`),\n
+  KEY (`metric_type_uid`)\n
+) TYPE=InnoDB;\n
+</string> </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.catalog_keys.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.catalog_keys.xml
new file mode 100644
index 0000000000..7d6996cb9c
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.catalog_keys.xml
@@ -0,0 +1,2 @@
+<catalog_method>
+</catalog_method>
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.xml
new file mode 100644
index 0000000000..f842fb69d6
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_metric_type.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <tuple>
+        <global name="SQL" module="Products.ZSQLMethods.SQL"/>
+        <tuple/>
+      </tuple>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__ac_local_roles__</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_arg</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="Args" module="Shared.DC.ZRDB.Aqueduct"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_data</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>table_0</string> </key>
+                                <value>
+                                  <dictionary/>
+                                </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>_keys</string> </key>
+                        <value>
+                          <list>
+<string>table_0</string>
+                          </list>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_owner</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>allow_simple_one_argument_traversal</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>arguments_src</string> </key>
+            <value> <string>table_0</string> </value>
+        </item>
+        <item>
+            <key> <string>cache_time_</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>class_file_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>class_name_</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>connection_hook</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>connection_id</string> </key>
+            <value> <string>erp5_sql_connection</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>z_related_metric_type</string> </value>
+        </item>
+        <item>
+            <key> <string>max_cache_</string> </key>
+            <value> <int>100</int> </value>
+        </item>
+        <item>
+            <key> <string>max_rows_</string> </key>
+            <value> <int>1000</int> </value>
+        </item>
+        <item>
+            <key> <string>src</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<dtml-var table_0>.resource_uid = resource.uid
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>template</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="__newobj__" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="SQL" module="Shared.DC.ZRDB.DA"/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>__name__</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<string>
+
+]]></string> </value>
+                    </item>
+                    <item>
+                        <key> <string>_vars</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>globals</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                    <item>
+                        <key> <string>raw</string> </key>
+                        <value> <string encoding="cdata"><![CDATA[
+
+<dtml-var table_0>.resource_uid = resource.uid
+
+]]></string> </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml
index ec38cbc28d..7dc1d7ce01 100644
--- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogRelatedKeyTemplateItem/related_key_list.xml
@@ -10,6 +10,7 @@
  <key>item_node_category_uid | category/category_uid/z_related_node_uid_from_item</key>
  <key>item_resource_category_uid | category/category_uid/z_related_resource_uid_from_item</key>
  <key>item_section_category_uid | category/category_uid/z_related_section_uid_from_item</key>
+ <key>metric_type_uid | measure/metric_type_uid/z_related_metric_type</key>
  <key>parent_description | catalog/description/z_related_parent</key>
  <key>parent_float_index | catalog/float_index/z_related_parent</key>
  <key>parent_int_index | catalog/int_index/z_related_parent</key>
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision
index e3b5acb834..615088b548 100644
--- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/revision
@@ -1 +1 @@
-107
\ No newline at end of file
+108
\ No newline at end of file
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_method_id_list b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_method_id_list
index a1b2dbdc11..daa1e42508 100644
--- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_method_id_list
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_method_id_list
@@ -6,6 +6,7 @@ erp5_mysql_innodb/z0_drop_fulltext
 erp5_mysql_innodb/z0_drop_inventory
 erp5_mysql_innodb/z0_drop_inventory_stock
 erp5_mysql_innodb/z0_drop_item
+erp5_mysql_innodb/z0_drop_measure
 erp5_mysql_innodb/z0_drop_movement
 erp5_mysql_innodb/z0_drop_portal_ids
 erp5_mysql_innodb/z0_drop_predicate
@@ -20,6 +21,7 @@ erp5_mysql_innodb/z0_uncatalog_fulltext
 erp5_mysql_innodb/z0_uncatalog_inventory
 erp5_mysql_innodb/z0_uncatalog_inventory_stock
 erp5_mysql_innodb/z0_uncatalog_item
+erp5_mysql_innodb/z0_uncatalog_measure
 erp5_mysql_innodb/z0_uncatalog_movement
 erp5_mysql_innodb/z0_uncatalog_predicate
 erp5_mysql_innodb/z0_uncatalog_predicate_category
@@ -30,6 +32,7 @@ erp5_mysql_innodb/z_catalog_fulltext_list
 erp5_mysql_innodb/z_catalog_inventory_list
 erp5_mysql_innodb/z_catalog_inventory_stock_list
 erp5_mysql_innodb/z_catalog_item_list
+erp5_mysql_innodb/z_catalog_measure_list
 erp5_mysql_innodb/z_catalog_movement_category_list
 erp5_mysql_innodb/z_catalog_movement_list
 erp5_mysql_innodb/z_catalog_non_movement_category_list
@@ -50,6 +53,7 @@ erp5_mysql_innodb/z_create_fulltext
 erp5_mysql_innodb/z_create_inventory
 erp5_mysql_innodb/z_create_inventory_stock
 erp5_mysql_innodb/z_create_item
+erp5_mysql_innodb/z_create_measure
 erp5_mysql_innodb/z_create_movement
 erp5_mysql_innodb/z_create_portal_ids
 erp5_mysql_innodb/z_create_predicate
@@ -72,6 +76,7 @@ erp5_mysql_innodb/z_related_base_category_id
 erp5_mysql_innodb/z_related_career_skill
 erp5_mysql_innodb/z_related_explanation
 erp5_mysql_innodb/z_related_grand_parent
+erp5_mysql_innodb/z_related_metric_type
 erp5_mysql_innodb/z_related_mirror_section_uid_from_stock
 erp5_mysql_innodb/z_related_node_uid_from_stock
 erp5_mysql_innodb/z_related_parent
diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_related_key_list b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_related_key_list
index 4e1afe8f50..473dfa94c6 100644
--- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_related_key_list
+++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/bt/template_catalog_related_key_list
@@ -41,4 +41,5 @@ parent_reference | catalog/reference/z_related_parent
 parent_description | catalog/description/z_related_parent
 parent_portal_type | catalog/portal_type/z_related_parent
 translated_causality_state | translation/translated_message/z_related_translated_causality_state
-translated_causality_state_title | translation/translated_message/z_related_translated_causality_state_title
\ No newline at end of file
+translated_causality_state_title | translation/translated_message/z_related_translated_causality_state_title
+metric_type_uid | measure/metric_type_uid/z_related_metric_type
\ No newline at end of file
diff --git a/product/ERP5/tests/testInventoryAPI.py b/product/ERP5/tests/testInventoryAPI.py
index 25ae921f88..0623c67541 100644
--- a/product/ERP5/tests/testInventoryAPI.py
+++ b/product/ERP5/tests/testInventoryAPI.py
@@ -58,7 +58,15 @@ class InventoryAPITestCase(ERP5TypeTestCase):
                        'group/test_group/A2/B1/C2',
                        'group/test_group/A2/B2/C1',
                        'group/test_group/A2/B2/C2', )
-  
+
+  VARIATION_CATEGORIES = ( 'colour/red',
+                           'colour/green',
+                           'colour/blue',
+                           'size/big',
+                           'size/small',
+                           'industrial_phase/phase1',
+                           'industrial_phase/phase2', )
+
   def getTitle(self):
     """Title of the test."""
     return 'Inventory API'
@@ -181,7 +189,7 @@ class InventoryAPITestCase(ERP5TypeTestCase):
               'group/anotherlevel',
               'product_line/level1/level2',
            # we create a huge group category for consolidation tests
-           ) + self.GROUP_CATEGORIES
+           ) + self.GROUP_CATEGORIES + self.VARIATION_CATEGORIES
   
   def getBusinessTemplateList(self):
     """ erp5_trade is required for transit_simulation_state
@@ -2085,6 +2093,110 @@ class TestInventoryDocument(InventoryAPITestCase):
       _aq_reset()
 
 
+class TestUnitConversion(InventoryAPITestCase):
+  QUANTITY_UNIT_CATEGORIES = {
+    'unit': {'unit': 1, 'a_few': None},
+    'length': {'m': 1, 'in': .0254},
+    'mass': {'kg': 1, 't': 1000, 'g': .001},
+  }
+  METRIC_TYPE_CATEGORIES = (
+    'unit',
+    'unit/0',
+    'unit/1',
+    'unit/2',
+    'mass/net',
+    'mass/nutr/lipid',
+  )
+
+  def afterSetUp(self):
+    InventoryAPITestCase.afterSetUp(self)
+
+    self.resource.setQuantityUnitList(('unit/unit', 'length/in'))
+    self.other_resource.setQuantityUnit('mass/g')
+
+    keys = ('metric_type', 'quantity_unit', 'quantity', 'default_metric_type')
+    for resource, measure_list in {
+        self.resource: (
+          ('mass/net',        'mass/kg', .123, None),
+          ('mass/nutr/lipid', 'mass/g',  45,   True),
+        ),
+        self.other_resource: (
+          # default measure (only useful to set the metric type)
+          ('mass/net', None,        1,    True),
+          # Bad measures
+          ('unit',    'unit/unit',  123,  None), ## duplicate
+          ('unit',    'unit/unit',  123,  None), #
+          ('unit/0',  'unit/a_few', 123,  None), ## incomplete
+          ('unit/1',  'unit/unit',  None, None), #
+          ('unit/2',  None,         123,  None), #
+          (None,      'mass/kg',    123,  None), #
+          (None,      None,         None, None), ## empty
+        )}.iteritems():
+      for measure in measure_list:
+        kw = dict((keys[i], v) for i, v in enumerate(measure) if v is not None)
+        resource.newContent(portal_type='Measure', **kw)
+
+    self.resource.setOptionalVariationBaseCategory('industrial_phase')
+    self.resource.setVariationBaseCategoryList(('colour', 'size'))
+    self.resource.setVariationCategoryList(self.VARIATION_CATEGORIES)
+    m = self.resource.getDefaultMeasure('mass/t')
+
+    m.setMeasureVariationBaseCategory('colour')
+    for colour, quantity in ('green', 43), ('red', 56):
+      m.newContent(portal_type='Measure Cell', quantity=quantity) \
+       ._setMembershipCriterionCategory('colour/' + colour)
+
+    self._safeTic()
+
+  def getNeededCategoryList(self):
+    category_list = ['metric_type/' + c for c in self.METRIC_TYPE_CATEGORIES]
+    for level1, level2 in self.QUANTITY_UNIT_CATEGORIES.iteritems():
+      quantity = 'quantity_unit/%s/' % level1
+      category_list.extend(quantity + unit for unit in level2)
+    category_list += InventoryAPITestCase.getNeededCategoryList(self)
+    return category_list
+
+  def createCategories(self):
+    InventoryAPITestCase.createCategories(self)
+    quantity_unit = self.getCategoryTool().quantity_unit
+    for quantity_id, unit_dict in self.QUANTITY_UNIT_CATEGORIES.iteritems():
+      quantity_value = quantity_unit[quantity_id]
+      for unit_id, unit_scale in unit_dict.iteritems():
+        if unit_scale is not None:
+          quantity_value[unit_id].setProperty('quantity', unit_scale)
+
+  def testConvertedInventoryList(self):
+    def makeMovement(quantity, resource, *variation, **kw):
+      m = self._makeMovement(quantity=quantity, resource_value=resource,
+        source_value=self.node, destination_value=self.mirror_node, **kw)
+      if variation:
+        m.setVariationCategoryList(variation)
+        self._safeTic()
+
+    makeMovement(2, self.resource, 'colour/green', 'size/big')
+    makeMovement(789, self.other_resource)
+    makeMovement(-13, self.resource, 'colour/red', 'size/small',
+                 'industrial_phase/phase1', 'industrial_phase/phase2')
+
+    def simulation(metric_type, **kw):
+      return self.getSimulationTool().getConvertedInventoryList(
+        metric_type=metric_type, node_uid=self.node.getUid(),
+        ignore_group_by=1, inventory_list=0, **kw)[0].converted_quantity
+
+    for i in range(3):
+      self.assertEquals(None, simulation('unit/%i' % i))
+
+    self.assertEquals(None, simulation('unit', simulation_period='Current'))
+    self.assertEquals(11, simulation('unit'))
+
+    self.assertEquals(11 * 123 - 789,
+                      simulation('mass/net', quantity_unit=.001))
+    self.assertEquals((11 * 123 - 789) / 1e6,
+                      simulation('mass/net', quantity_unit='mass/t'))
+
+    self.assertEquals(13 * .056 - 2 * .043, simulation('mass/nutr/lipid'))
+
+
 def test_suite():
   suite = unittest.TestSuite()
   suite.addTest(unittest.makeSuite(TestInventory))
@@ -2094,6 +2206,7 @@ def test_suite():
   suite.addTest(unittest.makeSuite(TestNextNegativeInventoryDate))
   suite.addTest(unittest.makeSuite(TestTrackingList))
   suite.addTest(unittest.makeSuite(TestInventoryDocument))
+  suite.addTest(unittest.makeSuite(TestUnitConversion))
   return suite
 
 # vim: foldmethod=marker
diff --git a/product/ERP5Type/Utils.py b/product/ERP5Type/Utils.py
index 2ef40914a6..8bafd03d26 100644
--- a/product/ERP5Type/Utils.py
+++ b/product/ERP5Type/Utils.py
@@ -2505,3 +2505,102 @@ def getCommonTimeZoneList():
   """ Get common (country/capital(major cities) format) timezones list """
   from pytz import common_timezones
   return common_timezones
+
+
+#####################################################
+# Processing of ZRDB.Results objects
+#####################################################
+
+from Shared.DC.ZRDB.Results import Results
+
+def mergeZRDBResults(results, key_column, edit_result):
+  """
+  Merge several ZRDB.Results into a single ZRDB.Results. It's done in 3 steps:
+   1. Rename columns of every table (cf 1st parameter).
+   2. Merge all source tables into a intermediate sparse table.
+      Each processed row is identified according to the columns specified in the
+      2nd parameter: Rows with the same values in the specified columns are
+      merged together, otherwise they are stored separately.
+   3. Convert the intermediate table into a ZRDB.Results structure.
+      Cell values are copied or created according the 3rd parameter.
+      By default, values aren't modified and empty cells are set to None.
+
+  results     - List of ZRDB.Results to merge. Each item can also be a tuple
+                (ZRDB.Results, rename_map) : the columns are renamed before
+                any other processing, according to rename_map (dict).
+  key_column  - 2 rows are merged if and only if there is the same value in
+                the common column(s) specified by key_column.
+                key_column can be either a string or a sequence of strings.
+                () can be passed to merge 1-row tables.
+  edit_result - Map { column_name: function | defaut_value } allowing to edit
+                values (or specify default values) for certain columns in the
+                resulting table:
+                 - function (lambda row, column_name: new_value)
+                 - default_value is interpreted as
+                   (lambda row, column: row.get(column, default_value))
+                Note that whenever a row doesn't have a matching row in every
+                other table, the merged result before editing may contain
+                incomplete rows. get_value also allows you to fill these rows
+                with specific values, instead of the default 'None' value.
+  """
+  if isinstance(key_column,str):
+    key_column = key_column,
+
+  ## Variables holding the resulting table:
+  items = [] # list of columns: each element is an item (cf ZRDB.Results)
+  column_list = [] # list of columns:
+                   # each element is a pair (column name, get_value)
+  data = [] # list of rows of maps column_name => value
+
+  ## For each key, record the row number in 'data'
+  index = {}
+
+  ## Set of columns already seen
+  column_set = set()
+
+  for r in results:
+    ## Step 1
+    if isinstance(r, Results):
+      rename = {}
+    else:
+      r, rename = r
+    new_column_list = []
+    columns = {}
+    for i, column in enumerate(r._searchable_result_columns()):
+      name = column['name']
+      name = rename.get(name, name)
+      if name is None:
+        continue
+      columns[name] = i
+      if name not in column_set:
+        column_set.add(name)
+        new_column_list.append(i)
+        column = column.copy()
+        column['name'] = name
+        items.append(column)
+        # prepare step 3
+        get_value = edit_result.get(name)
+        column_list += (name, hasattr(get_value, '__call__') and get_value or
+          (lambda row, column, default=get_value: row.get(column, default))),
+
+    ## Step 2
+    try:
+      index_pos = [ columns[rename.get(name,name)] for name in key_column ]
+    except KeyError:
+      raise KeyError("Missing '%s' column in source table" % name)
+    for row in r:
+      key = tuple(row[i] for i in index_pos)
+      if key in index: # merge the row to an existing one
+        merged_row = data[index[key]]
+      else: # new row
+        index[key] = len(data)
+        merged_row = {}
+        data.append(merged_row)
+      for column, i in columns.iteritems():
+        merged_row[column] = row[i]
+
+  ## Step 3
+  return Results((items, [
+      [ get_value(row, column) for column, get_value in column_list ]
+      for row in data
+    ]))
-- 
2.30.9