From 6edaa9b6e63bb617f67d69693505d38e3a83fc62 Mon Sep 17 00:00:00 2001
From: Vincent Pelletier <vincent@nexedi.com>
Date: Wed, 10 Jul 2013 14:29:03 +0200
Subject: [PATCH] Rework Folder_generateWorkflowReport

Add support for honoring user selection, and related option (enabled by default).
Query catalog only once.
Do not use custom ZSQLMethod.
---
 .../erp5_core/Base_zCountByWorkflowState.xml  | 119 ---------------
 .../Folder_generateWorkflowReport.xml         | 141 +++++++++---------
 .../Folder_generateWorkflowReportDialog.xml   |   1 +
 .../your_use_selection.xml                    | 101 +++++++++++++
 4 files changed, 171 insertions(+), 191 deletions(-)
 delete mode 100644 product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_zCountByWorkflowState.xml
 create mode 100644 product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog/your_use_selection.xml

diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_zCountByWorkflowState.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_zCountByWorkflowState.xml
deleted file mode 100644
index d393af98da..0000000000
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_zCountByWorkflowState.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="SQL" module="Products.ZSQLMethods.SQL"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_col</string> </key>
-            <value>
-              <list>
-                <dictionary>
-                  <item>
-                      <key> <string>name</string> </key>
-                      <value> <string>validation_state</string> </value>
-                  </item>
-                  <item>
-                      <key> <string>null</string> </key>
-                      <value> <int>1</int> </value>
-                  </item>
-                  <item>
-                      <key> <string>type</string> </key>
-                      <value> <string>t</string> </value>
-                  </item>
-                  <item>
-                      <key> <string>width</string> </key>
-                      <value> <int>5</int> </value>
-                  </item>
-                </dictionary>
-                <dictionary>
-                  <item>
-                      <key> <string>name</string> </key>
-                      <value> <string>count(*)</string> </value>
-                  </item>
-                  <item>
-                      <key> <string>null</string> </key>
-                      <value> <int>0</int> </value>
-                  </item>
-                  <item>
-                      <key> <string>type</string> </key>
-                      <value> <string>l</string> </value>
-                  </item>
-                  <item>
-                      <key> <string>width</string> </key>
-                      <value> <int>2</int> </value>
-                  </item>
-                </dictionary>
-              </list>
-            </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>portal_type=""\r\n
-state_name=""</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>ZSQLCatalog.zsqlbrain</string> </value>
-        </item>
-        <item>
-            <key> <string>class_name_</string> </key>
-            <value> <string>ZSQLBrain</string> </value>
-        </item>
-        <item>
-            <key> <string>connection_hook</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>Base_zCountByWorkflowState</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[
-
-SELECT catalog.<dtml-var expr="state_name">, count(*)\n
-FROM catalog\n
-\n
-WHERE\n
-\n
-catalog.portal_type = "<dtml-var expr="portal_type">"\n
-\n
-GROUP BY catalog.<dtml-var expr="state_name">\n
-\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReport.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReport.xml
index 130bac95fa..8edfebc6c7 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReport.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReport.xml
@@ -50,84 +50,81 @@
         </item>
         <item>
             <key> <string>_body</string> </key>
-            <value> <string>listbox = []\n
-result_dict = {}\n
-translate_state_dict = {}\n
-state_dict={}\n
-portal_type_dict={}\n
-workflow_dict={}\n
-portal_workflow = context.portal_workflow\n
-content_type_list = context.allowedContentTypes()\n
-content_type_list.sort()\n
-\n
-translateString = context.Base_translateString\n
-\n
-workflow_tool = context.portal_workflow\n
-for portal_type in content_type_list:\n
+            <value> <string encoding="cdata"><![CDATA[
+
+portal = context.getPortalObject()\n
+translateString = portal.Base_translateString\n
+getWorkflowsFor = portal.portal_workflow.getWorkflowsFor\n
+state_variable_set = set()\n
+add = state_variable_set.add\n
+type_state_variable_workflow_dict = {}\n
+type_workflow_state_count_dict_dict = {}\n
+workflow_translated_title_dict = {}\n
+workflow_translated_state_title_dict = {}\n
+portal_type_translated_title_dict = {}\n
+for portal_type in context.allowedContentTypes():\n
   portal_type_id = portal_type.getId()\n
-  workflow_list = workflow_tool.getWorkflowsFor(portal_type_id)\n
-  # Retrieve the workflows by portal_type\n
-  for workflow in workflow_list:\n
-    # not \'edit_workflow\' because state variable is not in catalog\n
-    if getattr(workflow, \'states\', None) is not None and \\\n
-      workflow.getId() != \'edit_workflow\':\n
-      #retrieve state_var to search in the catalog the states use by the\n
-      #workflow\n
+  portal_type_translated_title_dict[portal_type_id] = translateString(portal_type.getTitle())\n
+  for workflow in getWorkflowsFor(portal_type_id):\n
+    state_container = getattr(workflow, \'states\', None)\n
+    if state_container is not None and len(state_container) > 1:\n
       state_var = workflow.state_var\n
-      result_list = context.Base_zCountByWorkflowState(portal_type=portal_type_id,\n
-                                                       state_name=state_var)\n
-      if not ((len(result_list) == 1) and (result_list[0][0] is None)):\n
-        for result in result_list:\n
-          portal_type_dict = result_dict.get(portal_type_id,{})\n
-          workflow_dict = portal_type_dict.get(workflow.title,{})\n
-          workflow_dict.update({result[0]:result[1]})\n
-          portal_type_dict.update({workflow.title:workflow_dict})\n
-          result_dict.update({portal_type_id:portal_type_dict})\n
-          # store the title states for the translation\n
-          if not translate_state_dict.has_key(result[0]):\n
-            state_title = getattr(workflow.states, result[0]).title_or_id()\n
-            translate_state_dict[result[0]] = state_title\n
-\n
-#Display the result\n
-state_list_dict = {}\n
-portal_type_list = result_dict.keys()\n
-portal_type_list.sort()\n
-for portal_type in portal_type_list:\n
-  workflow_list = result_dict[portal_type].keys()\n
-  for workflow_title in workflow_list:\n
-    listbox.append({\'translated_portal_type\': \'%s - %s\' %\\\n
-      (translateString(portal_type), translateString(workflow_title)),\n
-                    \'state\'      : \'\',\n
-                    \'count\'      : \'\'})\n
-    state_list = result_dict[portal_type][workflow_title].keys()\n
-    state_list.sort()\n
-    for state in state_list:\n
-      result_count = result_dict[portal_type][workflow_title][state]\n
-      count = state_list_dict.get(state, 0) + result_count\n
-      # account the number of items by state\n
-      state_list_dict.update({state:count})\n
-      listbox.append({\'translated_portal_type\': \'\',\n
-                      \'state\'      : translateString(translate_state_dict[state]),\n
-                      \'count\'      : result_count})\n
-\n
-#Display the total by state\n
-listbox.append({\'translated_portal_type\': translateString(\'All\'),\n
-                \'state\'      : \'\',\n
-                \'count\'      : \'\'})\n
-state_list = state_list_dict.keys()\n
-state_list.sort()\n
-for state in state_list:\n
-  listbox.append({\'translated_portal_type\': \'\',\n
-                  \'state\'      : translateString(translate_state_dict[state]),\n
-                  \'count\'      : state_list_dict[state]})\n
-\n
-context.Base_updateDialogForm(listbox=listbox, empty_line_number=0)\n
+      workflow_id = workflow.getId()\n
+      workflow_translated_title_dict[workflow_id] = translateString(workflow.title)\n
+      type_state_variable_workflow_dict[(portal_type_id, state_var)] = workflow_id\n
+      state_count_dict = type_workflow_state_count_dict_dict.setdefault((portal_type_id, workflow_id), {})\n
+      translated_state_title_dict = workflow_translated_state_title_dict.setdefault(workflow_id, {})\n
+      for state in state_container.objectValues():\n
+        state_id = state.getId()\n
+        # TODO: support workflow-specific translations\n
+        translated_state_title_dict[state_id] = translateString(state.title)\n
+        state_count_dict[state_id] = 0\n
+      add(state_var)\n
+column_list = [\'portal_type\'] + list(state_variable_set)\n
+COUNT = \'count(*)\'\n
+if use_selection:\n
+  selection_kw = portal.portal_selections.getSelectionParamsFor(selection_name).copy()\n
+  selection_kw.pop(\'limit\', None)\n
+  query = portal.portal_catalog.getSQLCatalog().buildQuery(selection_kw)\n
+else:\n
+  query = None\n
+for line in context.searchFolder(group_by=column_list, select_list=[COUNT] + column_list, query=query):\n
+  portal_type = line.portal_type\n
+  count = getattr(line, COUNT)\n
+  for state_variable in state_variable_set:\n
+    workflow = type_state_variable_workflow_dict.get((line.portal_type, state_variable))\n
+    state = getattr(line, state_variable)\n
+    if workflow is None:\n
+      assert not state, (portal_type, state_variable, state)\n
+      continue\n
+    state_count_dict = type_workflow_state_count_dict_dict[(portal_type, workflow)]\n
+    state_count_dict[state] = count + state_count_dict[state]\n
+listbox = []\n
+append = listbox.append\n
+for (portal_type, workflow), state_count_dict in sorted(type_workflow_state_count_dict_dict.iteritems(), key=lambda x: x[0]):\n
+  if sum(state_count_dict.values()):\n
+    append({\n
+      \'translated_portal_type\': \'%s - %s\' % (portal_type_translated_title_dict[portal_type], workflow_translated_title_dict[workflow]),\n
+      \'state\' : \'\',\n
+      \'count\' : \'\',\n
+    })\n
+    translated_state_title_dict = workflow_translated_state_title_dict[workflow]\n
+    for state, count in sorted(state_count_dict.iteritems(), key=lambda x: x[0]):\n
+      if count:\n
+        append({\n
+          \'translated_portal_type\': \'\',\n
+          \'state\': translated_state_title_dict[state],\n
+          \'count\': count,\n
+        })\n
+portal.Base_updateDialogForm(listbox=listbox, empty_line_number=0)\n
 return context.Folder_viewWorkflowReport()\n
-</string> </value>
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>_params</string> </key>
-            <value> <string></string> </value>
+            <value> <string>use_selection, selection_name</string> </value>
         </item>
         <item>
             <key> <string>_proxy_roles</string> </key>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog.xml
index b4fe183eaa..5ec046da29 100644
--- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog.xml
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog.xml
@@ -73,6 +73,7 @@
                       <list>
                         <string>your_format</string>
                         <string>your_portal_skin</string>
+                        <string>your_use_selection</string>
                       </list>
                     </value>
                 </item>
diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog/your_use_selection.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog/your_use_selection.xml
new file mode 100644
index 0000000000..4b4cfc72c0
--- /dev/null
+++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Folder_generateWorkflowReportDialog/your_use_selection.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>default</string>
+                <string>title</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>your_use_selection</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>default</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <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>Use Current Selection</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
-- 
2.30.9