diff --git a/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_calculateStatistics.xml b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_calculateStatistics.xml new file mode 100644 index 0000000000000000000000000000000000000000..09a9545ed8e1c1db2adf428a0c1e64dad395bb29 --- /dev/null +++ b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_calculateStatistics.xml @@ -0,0 +1,259 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <tuple> + <tuple> + <string>Products.PythonScripts.PythonScript</string> + <string>PythonScript</string> + </tuple> + <none/> + </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>"""\n + A simple script to calculate some statistics\n + about documents and persons in the system.\n +\n +"""\n +from Products.ERP5Type.Cache import CachingMethod\n +\n +def sortDictByValues(adict):\n + """ \n + Sort a dictionary by maximal values. \n + Return sorted list of tuples [(key, value),...]\n + """\n + items = adict.items()\n + items.sort(lambda x,y: cmp(x[1], y[1]))\n + items.reverse()\n + return items\n +\n +def calculateStatistics():\n + portal = context.getPortalObject()\n + portal_catalog = portal.portal_catalog\n + portal_types = context.portal_types\n +\n + # document statistics\n + documents_groups = {}\n + documents_owners = {}\n + documents_classifications = {}\n + document_content_types = portal_types[\'Document Module\'].allowed_content_types\n + all_documents = portal_catalog.searchResults(portal_type = document_content_types)\n + total_documents = portal_catalog.countResults(portal_type = document_content_types)[0][0]\n + total_documents_released = portal_catalog.countResults(portal_type = document_content_types,\n + validation_state = \'released\')[0][0]\n + total_documents_shared = portal_catalog.countResults(portal_type = document_content_types,\n + validation_state = \'shared\')[0][0]\n + total_documents_draft = portal_catalog.countResults(portal_type = document_content_types,\n + validation_state = \'draft\')[0][0]\n + total_documents_published = portal_catalog.countResults(portal_type = document_content_types,\n + validation_state = \'published\')[0][0]\n + # get what\'s still not in catalog as info\n + for doc in all_documents:\n + obj = doc.getObject()\n + # count classification\n + classification = obj.getClassification()\n + if classification is not None:\n + documents_classifications[classification] = documents_classifications.get(classification, 0) + 1\n + # count devision\n + group = obj.getGroup()\n + if group is not None:\n + documents_groups[group] = documents_groups.get(group, 0) + 1\n + # XXX: count owner\n + doc_metadata = portal_catalog.getMetadataForUid(doc.getUid())\n + doc_owner = doc_metadata.get(\'owner\', None)\n + if doc_owner is not None and doc_owner.find(\'@\')!=-1:\n + # we have a website user. we wanted to filter Zope users\n + documents_owners[doc_owner] = documents_owners.get(doc_owner, 0) + 1\n + # sort the most "productive" devision group by number of documents contributed\n + documents_groups_sorted = sortDictByValues(documents_groups)\n + # sort sort the most "productive" person by number of documents contributed\n + documents_owners_sorted = sortDictByValues(documents_owners)\n + documents_stats = dict(total_documents = total_documents,\n + total_documents_released = total_documents_released,\n + total_documents_shared = total_documents_shared,\n + total_documents_draft = total_documents_draft,\n + total_documents_published = total_documents_published,\n + documents_groups_sorted = documents_groups_sorted,\n + documents_owners_sorted = documents_owners_sorted,\n + classifications = documents_classifications)\n + # person statistics\n + total_persons = portal_catalog.countResults(portal_type = \'Person\')[0][0]\n + total_persons_draft = portal_catalog.countResults(portal_type = \'Person\',\n + validation_state = \'draft\')[0][0]\n + total_persons_validated = portal_catalog.countResults(portal_type = \'Person\',\n + validation_state = \'validated\')[0][0]\n + persons_stats = dict(total_persons = total_persons,\n + total_persons_draft = total_persons_draft,\n + total_persons_validated = total_persons_validated)\n + # final statistics\n + statistics = dict(documents = documents_stats,\n + persons = persons_stats)\n + return statistics\n +\n +# cache statistics for a short period\n +cached_method = CachingMethod(calculateStatistics, \n + script.id, \n + \'erp5_content_short\')\n +stats = cached_method() #calculateStatistics()\n +\n +return stats\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>_owner</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>_params</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>_proxy_roles</string> </key> + <value> + <tuple> + <string>Anonymous</string> + <string>Assignee</string> + <string>Assignor</string> + <string>Associate</string> + <string>Auditor</string> + <string>Authenticated</string> + <string>Author</string> + <string>Manager</string> + <string>Member</string> + <string>Owner</string> + <string>Reviewer</string> + </tuple> + </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>Products.ERP5Type.Cache</string> + <string>CachingMethod</string> + <string>sortDictByValues</string> + <string>calculateStatistics</string> + <string>_getattr_</string> + <string>script</string> + <string>cached_method</string> + <string>stats</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>WebSite_calculateStatistics</string> </value> + </item> + <item> + <key> <string>warnings</string> </key> + <value> + <tuple/> + </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_viewDashboardRenderer.xml b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_viewDashboardRenderer.xml index 21bd1b8eaf52ea42be82bbb482ab7034c13c9cd6..04ae4c8b353d2761d0026408bceb33c70caa2ff2 100644 --- a/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_viewDashboardRenderer.xml +++ b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web_widget_library/WebSite_viewDashboardRenderer.xml @@ -51,7 +51,7 @@ <tal:block tal:define="NEWS_LEN NEWS_LEN | python:10;\n TASK_LEN TASK_LEN | python:10;">\n <tal:block metal:define-macro="act">\n - <tal:block tal:define="tasks python: list(here.WebSite_getPendingEventInfoList())[:TASK_LEN];">\n + <tal:block tal:define="tasks python: list(here.WebSite_getPendingEventInfoList())[:TASK_LEN];">\n <div class="boxHeader" >\n <a i18n:translate="" i18n:domain="ui"\n tal:attributes="href string: search_area/WebSite_viewPendingEventList">\n @@ -61,8 +61,8 @@ </div>\n <div class="boxContent">\n <ul>\n - <li tal:repeat="doc tasks">\n - <tal:block tal:condition="python:doc is not None">\n + <li tal:repeat="doc tasks">\n + <tal:block tal:condition="python:doc is not None">\n <a tal:define="url python: \'%s/view\' % doc.absolute_url()"\n tal:attributes="href url">\n <span tal:replace="doc/portal_type"/>:\n @@ -72,7 +72,7 @@ (<span tal:content="python: doc.getValidationStateTitle()" \n tal:attributes="class python:doc.getTranslatedValidationStateTitle()"/>)\n </a>\n - </tal:block>\n + </tal:block>\n </li>\n </ul>\n <a tal:condition="python: len(tasks) > TASK_LEN" \n @@ -111,12 +111,58 @@ </tal:block>\n \n <tal:block metal:define-macro="evaluate">\n - <tal:block>\n + <tal:block tal:define="stats here/WebSite_calculateStatistics;\n + persons_stats stats/persons;\n + document_stats stats/documents;">\n <div class="boxHeader" value="" i18n:translate="" i18n:domain="ui">\n Evaluate\n </div>\n <div class="boxContent">\n - Some nice evaluation parameters.\n + <h5>Documents (overall)</h5>\n + <ul>\n + <li>Published: <span tal:content="document_stats/total_documents_published"/></li>\n + <li>Released: <span tal:content="document_stats/total_documents_released"/></li>\n + <li>Shared: <span tal:content="document_stats/total_documents_shared"/></li>\n + <li>Draft: <span tal:content="document_stats/total_documents_draft"/></li>\n + <li>Total: <span tal:content="document_stats/total_documents"/></li>\n + </ul>\n +\n + <h5>Documents (classified)</h5>\n + <ul>\n + <li tal:repeat="classification python:document_stats[\'classifications\'].items()">\n + <tal:block tal:define="classification_obj python: here.restrictedTraverse(\'portal_categories/classification/%s\' %classification[0])">\n + <span tal:content="classification_obj/getTitle"/>: \n + <span tal:content="python: classification[1]"/>\n + </tal:block>\n + </li>\n + </ul>\n +\n + <h5>Most productive</h5>\n + <ul tal:define="group python: document_stats[\'documents_groups_sorted\'][0];\n + group_obj python: here.restrictedTraverse(\'portal_categories/group/%s\' %group[0]);\n + person python: document_stats[\'documents_owners_sorted\'][0];\n + person_obj python: here.ERP5Site_getAuthenticatedMemberPersonValue(person[0]);">\n + <li><b>Person:</b> \n + <a href="" tal:attributes="href person_obj/absolute_url">\n + <span tal:content="person_obj/getTitle"/>\n + (<span tal:content="python: person[1]"/>)\n + </a>\n + </li>\n + <li><b>Devision:</b> \n + <a href="" tal:attributes="href group_obj/absolute_url">\n + <span tal:content="group_obj/getTitle"/>\n + (<span tal:content="python: group[1]"/>)\n + </a>\n + </li>\n + </ul>\n +\n + <h5>Human Resources</h5>\n + <ul>\n + <li>Total: <span tal:content="persons_stats/total_persons"/></li>\n + <li>Validated: <span tal:content="persons_stats/total_persons_validated"/></li>\n + <li>Draft: <span tal:content="persons_stats/total_persons_draft"/></li>\n + </ul>\n +\n </div>\n </tal:block>\n </tal:block>\n