From bc95b8ccec4a6804cd1cfbf6f784e6b1c9bfe9c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Mon, 7 Jun 2010 13:29:50 +0000
Subject: [PATCH] allow to group rows returned by getMovementHistoryList to
 produce aggregation of movements (for example, by resource and by delivery)

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@36023 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../Resource_zGetMovementHistoryList.xml      | 22 ++++----
 product/ERP5/bootstrap/erp5_core/bt/revision  |  2 +-
 product/ERP5/tests/testInventoryAPI.py        | 53 ++++++++++++++++++-
 3 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml
index 5c08477669..6c26d605e4 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml
@@ -664,23 +664,24 @@ SELECT\n
   catalog.relative_url as relative_url,\n
   stock.date AS date,\n
 <dtml-if expr="precision is not None">\n
-  ROUND(stock.quantity, <dtml-var precision>) AS total_quantity,\n
-  ROUND(stock.total_price, <dtml-var precision>) AS total_price,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(ROUND(stock.quantity, <dtml-var precision>)) AS total_quantity,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(ROUND(stock.total_price, <dtml-var precision>)) AS total_price,\n
 <dtml-else>\n
-  stock.quantity AS total_quantity,\n
-  stock.total_price AS total_price,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(stock.quantity) AS total_quantity,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(stock.total_price) AS total_price,\n
 </dtml-if>\n
   stock.variation_text AS variation_text,\n
   stock.simulation_state AS simulation_state,\n
   stock.mirror_section_uid AS mirror_section_uid,\n
   stock.mirror_node_uid AS mirror_node_uid,\n
+  stock.function_uid AS function_uid,\n
+  stock.project_uid AS project_uid,\n
   node.uid AS node_uid,\n
   node.title AS node_title,\n
   node.relative_url AS node_relative_url,\n
   section.uid AS section_uid,\n
   section.title AS section_title,\n
   section.relative_url AS section_relative_url\n
-\n
 FROM\n
   stock\n
   <dtml-if section_filtered> INNER <dtml-else> LEFT </dtml-if>  \n
@@ -830,23 +831,24 @@ SELECT\n
   catalog.relative_url as relative_url,\n
   stock.date AS date,\n
 <dtml-if expr="precision is not None">\n
-  ROUND(stock.quantity, <dtml-var precision>) AS total_quantity,\n
-  ROUND(stock.total_price, <dtml-var precision>) AS total_price,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(ROUND(stock.quantity, <dtml-var precision>)) AS total_quantity,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(ROUND(stock.total_price, <dtml-var precision>)) AS total_price,\n
 <dtml-else>\n
-  stock.quantity AS total_quantity,\n
-  stock.total_price AS total_price,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(stock.quantity) AS total_quantity,\n
+  <dtml-if group_by_expression>SUM</dtml-if>(stock.total_price) AS total_price,\n
 </dtml-if>\n
   stock.variation_text AS variation_text,\n
   stock.simulation_state AS simulation_state,\n
   stock.mirror_section_uid AS mirror_section_uid,\n
   stock.mirror_node_uid AS mirror_node_uid,\n
+  stock.function_uid AS function_uid,\n
+  stock.project_uid AS project_uid,\n
   node.uid AS node_uid,\n
   node.title AS node_title,\n
   node.relative_url AS node_relative_url,\n
   section.uid AS section_uid,\n
   section.title AS section_title,\n
   section.relative_url AS section_relative_url\n
-\n
 FROM\n
   stock\n
   <dtml-if section_filtered> INNER <dtml-else> LEFT </dtml-if>  \n
diff --git a/product/ERP5/bootstrap/erp5_core/bt/revision b/product/ERP5/bootstrap/erp5_core/bt/revision
index 3dfef23a19..55f084bf95 100644
--- a/product/ERP5/bootstrap/erp5_core/bt/revision
+++ b/product/ERP5/bootstrap/erp5_core/bt/revision
@@ -1 +1 @@
-1598
\ No newline at end of file
+1599
\ No newline at end of file
diff --git a/product/ERP5/tests/testInventoryAPI.py b/product/ERP5/tests/testInventoryAPI.py
index 3e398ecb69..13ec736d26 100644
--- a/product/ERP5/tests/testInventoryAPI.py
+++ b/product/ERP5/tests/testInventoryAPI.py
@@ -92,7 +92,6 @@ class InventoryAPITestCase(ERP5TypeTestCase):
     """set up """
     self.createCategories()
     self.login()
-    self.portal = self.getPortal()
     if not hasattr(self.portal, 'testing_folder'):
       self.portal.newContent(portal_type='Folder',
                             id='testing_folder')
@@ -1670,6 +1669,58 @@ class TestMovementHistoryList(InventoryAPITestCase):
     self.assertEquals(0, mvt_history_list[1].debit_price)
     self.assertEquals(-4, mvt_history_list[1].credit_price)
 
+  def test_group_by_explanation(self):
+    getMovementHistoryList = self.getSimulationTool().getMovementHistoryList
+    delivery = self.folder.newContent(portal_type='Dummy Delivery',
+                                      destination_section_value=self.section,
+                                      source_section_value=self.mirror_section,
+                                      destination_value=self.node,
+                                      source_value=self.mirror_node,)
+    m1 = delivery.newContent(portal_type='Dummy Movement', quantity=1,
+                             price=3, resource_value=self.resource,
+                             start_date=DateTime(2010, 1, 1))
+    m2 = delivery.newContent(portal_type='Dummy Movement', quantity=1,
+                             price=2, resource_value=self.resource,
+                             start_date=DateTime(2010, 1, 1))
+    m3 = delivery.newContent(portal_type='Dummy Movement', quantity=1,
+                             price=7, resource_value=self.other_resource,
+                             start_date=DateTime(2010, 1, 2))
+    transaction.commit();
+    self.tic()
+    # sanity check, our fake movements are all created in the same delivery,
+    # and have a valid explanation uid
+    self.assertEquals(m1.getExplanationUid(),
+                      m2.getExplanationUid())
+    self.assertTrue(m1.getExplanationUid())
+    # also make sure they acquire from delivery
+    self.assertEquals(self.node, m1.getDestinationValue())
+
+    # group by explanation
+    mvt_history_list = getMovementHistoryList(node_uid=self.node.getUid(),
+                                              group_by=('explanation_uid',), )
+    self.assertEquals(1, len(mvt_history_list))
+    self.assertEquals(3, mvt_history_list[0].total_quantity)
+    self.assertEquals(3, mvt_history_list[0].running_total_quantity)
+    self.assertEquals(12, mvt_history_list[0].total_price)
+    self.assertEquals(12, mvt_history_list[0].running_total_price)
+
+    # group by explanation and resource
+    mvt_history_list = getMovementHistoryList(node_uid=self.node.getUid(),
+                                              group_by=('explanation_uid',
+                                                        'resource_uid'),
+                                              sort_on=(('stock.date', 'ASC'),))
+    self.assertEquals(2, len(mvt_history_list))
+
+    self.assertEquals(2, mvt_history_list[0].total_quantity)
+    self.assertEquals(2, mvt_history_list[0].running_total_quantity)
+    self.assertEquals(5, mvt_history_list[0].total_price)
+    self.assertEquals(5, mvt_history_list[0].running_total_price)
+
+    self.assertEquals(1, mvt_history_list[1].total_quantity)
+    self.assertEquals(3, mvt_history_list[1].running_total_quantity)
+    self.assertEquals(7, mvt_history_list[1].total_price)
+    self.assertEquals(12, mvt_history_list[1].running_total_price)
+
 
 class TestNextNegativeInventoryDate(InventoryAPITestCase):
   """Tests getInventory methods.
-- 
2.30.9