[Erp5-report] r27216 - in /erp5/trunk/products/ERP5: ./ Document/ PropertySheet/ Tool/ boot...
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed May 27 17:19:13 CEST 2009
Author: seb
Date: Wed May 27 17:19:12 2009
New Revision: 27216
URL: http://svn.erp5.org?rev=27216&view=rev
Log:
Add Acknowledgement System that allows to find event that need to
be acknowledged by users with :
- portal_acknowledgement : tool that provided methods to retrieve
document to acknowledge and to acknowledge them
- new document class : Acknowledgement
- possibility to have proxy of Documents. Acknowledgements will only
be a proxy to event, the content of the message will not be kept
in the event, and we can access it from the Acknowledgement thanks
to the proxy
- the possibility to display site message on the top of the page
with xhtml style
- an unit test
Added:
erp5/trunk/products/ERP5/Document/Acknowledgement.py
erp5/trunk/products/ERP5/PropertySheet/DocumentProxy.py (with props)
erp5/trunk/products/ERP5/Tool/AcknowledgementTool.py
erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/bulletin_board.xml
erp5/trunk/products/ERP5/tests/testAcknowledgementTool.py
Modified:
erp5/trunk/products/ERP5/Document/Document.py
erp5/trunk/products/ERP5/Document/EmailDocument.py
erp5/trunk/products/ERP5/Document/Event.py
erp5/trunk/products/ERP5/ERP5Site.py
erp5/trunk/products/ERP5/__init__.py
erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/template_erp5_xhtml_style.xml
erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/bt/revision
Added: erp5/trunk/products/ERP5/Document/Acknowledgement.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Acknowledgement.py?rev=27216&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/Document/Acknowledgement.py (added)
+++ erp5/trunk/products/ERP5/Document/Acknowledgement.py [utf8] Wed May 27 17:19:12 2009
@@ -1,0 +1,80 @@
+##############################################################################
+#
+# Copyright (c) 2009 Nexedi SARL and Contributors. All Rights Reserved.
+# Ben Mayhew <maybewhen at gmx.net>
+# Sebastien Robin <seb at nexedi.com>
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+##############################################################################
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
+
+from Products.ERP5.Document.EmailDocument import EmailDocumentProxyMixin
+from Products.ERP5.Document.Event import Event
+
+class Acknowledgement(EmailDocumentProxyMixin, Event):
+ """
+ goal :
+
+ Acts as a proxy to the message in the case of
+ - private email
+ - message displayed to the user ?
+
+ We need this proxy because the user might not have the right to access
+ to the original message, and we don't wish to duplicate the content of
+ the original message (which can use attachements).
+
+ Use Case:
+
+ - A Site Notification is created in order to notify to all people of a
+ company. Then every time an user will acknowledge the notification,
+ a new Acknowledgement is created.
+ """
+
+ meta_type = 'ERP5 Acknowledgement'
+ portal_type = 'Acknowledgement'
+ add_permission = Permissions.AddPortalContent
+ isPortalContent = 1
+ isRADContent = 1
+ isDelivery = 1
+
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+ # Declarative properties
+ property_sheets = ( PropertySheet.Base
+ , PropertySheet.XMLObject
+ , PropertySheet.CategoryCore
+ , PropertySheet.Document
+ , PropertySheet.DublinCore
+ , PropertySheet.Snapshot
+ , PropertySheet.Task
+ , PropertySheet.Url
+ , PropertySheet.Arrow
+ , PropertySheet.Event
+ , PropertySheet.Delivery
+ , PropertySheet.DocumentProxy
+ )
+
+
Modified: erp5/trunk/products/ERP5/Document/Document.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Document.py?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/Document.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/Document.py [utf8] Wed May 27 17:19:12 2009
@@ -375,6 +375,31 @@
document = document.__of__(self)
return document
+class DocumentProxyMixin:
+ """
+ Provides access to documents referenced by the follow_up field
+ """
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'index_html' )
+ def index_html(self, REQUEST, RESPONSE, format=None, **kw):
+ """ Only a proxy method """
+ self.getProxiedDocument().index_html(REQUEST, RESPONSE, format, **kw)
+
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'getProxiedDocument' )
+ def getProxiedDocument(self):
+ """
+ Try to retrieve the original document
+ """
+ proxied_document = self.getDocumentProxyValue()
+ if proxied_document is None:
+ raise ValueError("Unable to find a proxied document")
+ return proxied_document
+
class UpdateMixIn:
"""
Provides an API to compute a date index based on the update
@@ -1550,4 +1575,4 @@
# Cut the trailing part in http://www.some.site/at/trailing.html
# but not in http://www.some.site/at
base_url = '/'.join(base_url_list[:-1])
- return base_url
+ return base_url
Modified: erp5/trunk/products/ERP5/Document/EmailDocument.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/EmailDocument.py?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/EmailDocument.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/EmailDocument.py [utf8] Wed May 27 17:19:12 2009
@@ -38,8 +38,9 @@
from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
from Products.ERP5.Document.TextDocument import TextDocument
from Products.ERP5.Document.File import File
-from Products.ERP5.Document.Document import ConversionError
+from Products.ERP5.Document.Document import ConversionError, DocumentProxyMixin
from Products.ERP5.Tool.NotificationTool import buildEmailMessage
+from MethodObject import Method
from zLOG import LOG, INFO
@@ -61,6 +62,39 @@
_MARKER = []
file_name_regexp = 'name="([^"]*)"'
+
+
+class EmailDocumentProxyMixin(DocumentProxyMixin):
+ """
+ Provides access to documents referenced by the causality field
+ """
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+
+class ProxiedMethod(Method):
+ """
+ Accessort that retrieve methods directly on the proxy
+ """
+
+ def __init__(self, proxied_method_id):
+ self.proxied_method_id = proxied_method_id
+
+ def __call__(self, instance, *args, **kw):
+ proxied_document = instance.getProxiedDocument()
+ method = getattr(proxied_document, self.proxied_method_id)
+ return method(*args, **kw)
+
+# generate all proxy method on EmailDocumentProxyMixin
+for method_id in ('getTextContent', 'getTextFormat', 'hasFile',
+ 'getContentInformation', 'getAttachmentData',
+ 'getAttachmentInformationList'):
+ EmailDocumentProxyMixin.security.declareProtected(
+ Permissions.AccessContentsInformation,
+ method_id)
+ setattr(EmailDocumentProxyMixin, method_id,
+ ProxiedMethod(method_id))
class EmailDocument(File, TextDocument):
"""
Modified: erp5/trunk/products/ERP5/Document/Event.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Event.py?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/Event.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/Event.py [utf8] Wed May 27 17:19:12 2009
@@ -32,7 +32,62 @@
from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Document.EmailDocument import EmailDocument
-class Event(EmailDocument, Movement):
+class AcknowledgeableMixin:
+ """
+ Mixin class for all documents that we can acknowledge
+ """
+ # Declarative security
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+ security.declareProtected(Permissions.AccessContentsInformation, 'acknowledge')
+ def acknowledge(self, **kw):
+ """
+ Define what we want to do with acknowledgment.
+
+ Possibilities :
+ - do nothing
+ - add an Acknowledge document every time someone read
+ an event corresponding to this ticket
+ - we could even think to move the workflow forward
+ when all event have been acknowledge
+
+ Is the name buildAcknowledgement better ???
+ """
+ method = self._getTypeBasedMethod('acknowledge')
+ if method is not None:
+ return method(**kw)
+ return None
+
+ def hasAcknowledgementActivity(self, user_name=None):
+ """
+ We will check if there is some current activities running or not
+ """
+ tag = "%s_%s" % (user_name, self.getRelativeUrl())
+ result = False
+ # First look at activities, we check if an acknowledgement document
+ # is under reindexing
+ if self.portal_activities.countMessageWithTag(tag):
+ result = True
+ return result
+
+ security.declareProtected(Permissions.AccessContentsInformation, 'isAcknowledged')
+ def isAcknowledged(self, user_name=None):
+ """
+ Say if this ticket is already acknowledged or not by this user.
+ """
+ result = self.hasAcknowledgementActivity(user_name=user_name)
+ if not result:
+ # Check in the catalog if we can find an acknowledgement
+ person_value = self.ERP5Site_getAuthenticatedMemberPersonValue(
+ user_name=user_name)
+ if len(self.portal_catalog(portal_type='Acknowledgement',
+ causality_relative_url=self.getRelativeUrl(),
+ destination_relative_url=person_value.getRelativeUrl())) > 0:
+ result = True
+ return result
+
+class Event(EmailDocument, Movement, AcknowledgeableMixin):
"""
Event is the base class for all events in ERP5.
Modified: erp5/trunk/products/ERP5/ERP5Site.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/ERP5Site.py?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/ERP5Site.py [utf8] (original)
+++ erp5/trunk/products/ERP5/ERP5Site.py [utf8] Wed May 27 17:19:12 2009
@@ -1338,6 +1338,8 @@
addTool('ERP5 Test Tool', None)
if not p.hasObject('portal_password'):
addTool('ERP5 Password Tool', None)
+ if not p.hasObject('portal_acknowledgements'):
+ addTool('ERP5 Acknowledgement Tool', None)
# Add ERP5Type Tool
addTool = p.manage_addProduct['ERP5Type'].manage_addTool
Added: erp5/trunk/products/ERP5/PropertySheet/DocumentProxy.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/PropertySheet/DocumentProxy.py?rev=27216&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/PropertySheet/DocumentProxy.py (added)
+++ erp5/trunk/products/ERP5/PropertySheet/DocumentProxy.py [utf8] Wed May 27 17:19:12 2009
@@ -1,0 +1,34 @@
+##############################################################################
+#
+# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
+# Sebastien Robin <seb at nexedi.com>
+#
+# 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 DocumentProxy:
+ """
+ Document Proxy properties
+ """
+
+ _categories = ( 'document_proxy', )
Propchange: erp5/trunk/products/ERP5/PropertySheet/DocumentProxy.py
------------------------------------------------------------------------------
svn:executable = *
Added: erp5/trunk/products/ERP5/Tool/AcknowledgementTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Tool/AcknowledgementTool.py?rev=27216&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/Tool/AcknowledgementTool.py (added)
+++ erp5/trunk/products/ERP5/Tool/AcknowledgementTool.py [utf8] Wed May 27 17:19:12 2009
@@ -1,0 +1,173 @@
+##############################################################################
+#
+# Copyright (c) 2009 Nexedi SARL and Contributors. All Rights Reserved.
+# Ben Mayhew <maybewhen at gmx.net>
+# Sebastien Robin <seb at nexedi.com>
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+##############################################################################
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass, DTMLFile
+from Products.ERP5Type.Tool.BaseTool import BaseTool
+from Products.ERP5Type import Permissions
+from Products.ERP5 import _dtmldir
+from Products.ERP5.Document.Acknowledgement import Acknowledgement
+from zLOG import LOG
+from DateTime import DateTime
+from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery
+
+
+class AcknowledgementTool(BaseTool):
+ """
+ Provide an entry point to track reception of events
+
+ someone who can not view the ticket or the event
+ must be able to acknowledge reception of email
+ or of site message sent by CRM.
+
+ This tools take into account that for some kind of document,
+ acknowledgements are not created in advance. For Site Message,
+ acknowledgements will be created every time the user confirm that he has
+ read the information.
+
+ In the case of internal emails, acknowledgements are created in advance.
+
+ Use Case: who read the emails I sent ?
+ Use Case: who said OK to Site Message ?
+ """
+ id = 'portal_acknowledgements'
+ meta_type = 'ERP5 Acknowledgement Tool'
+ portal_type = 'Acknowledgement Tool'
+ allowed_types = ('ERP5 Acknowledgement',)
+ # Declarative Security
+ security = ClassSecurityInfo()
+
+
+ security.declarePublic('getUnreadAcknowledgementList')
+ def countUnread(self, *args, **kw):
+ """
+ counts number of acknowledgements pending
+ """
+ return len(self.getUnreadAcknowledgementList(*args, **kw))
+
+ security.declarePublic('getUnreadAcknowledgementList')
+ def getUnreadAcknowledgementList(self, portal_type=None, user_name=None,
+ url_list=None):
+ """
+ returns acknowledgements pending
+ in the form of
+ - TempAcknowledgement (for Site Message)
+ - Acknowledgement (internal email)
+ """
+ portal = self.getPortalObject()
+ return_list = []
+ if url_list is None:
+ url_list = self.getUnreadDocumentUrlList(portal_type=portal_type,
+ user_name=user_name)
+ for url in url_list:
+ document = portal.restrictedTraverse(url)
+ if not document.isAcknowledged(user_name=user_name):
+ # If the document to acknowledge is a ticket, we should return
+ # a temp acknowledgement
+ if document.getPortalType() in portal.getPortalEventTypeList():
+ module = portal.getDefaultModule('Acknowledgement')
+ temp_acknowledgement = module.newContent(
+ portal_type='Acknowledgement',
+ temp_object=1,
+ document_proxy=document.getRelativeUrl(),
+ causality=document.getRelativeUrl())
+ return_list.append(temp_acknowledgement)
+ else:
+ # If not an event, this means that we have directly the document
+ # that we must acknowledge
+ return_list.append(document)
+ return return_list
+
+ security.declarePublic('getUnreadDocumentUrlList')
+ def getUnreadDocumentUrlList(self, portal_type=None, user_name=None, **kw):
+ """
+ returns document that needs to be acknowledged :
+ - Acknowledgement (internal email)
+ - Site Message
+
+ This method will mainly be used by getUnreadAcknowledgementList. Also,
+ because url are used, the result will be easy to cache.
+ """
+ document_list = []
+ if user_name is not None:
+ portal = self.getPortalObject()
+ now = DateTime()
+ # First look at all event that define the current user as destination
+ all_document_list = [x for x in \
+ self.portal_catalog(portal_type = portal_type,
+ simulation_state = self.getPortalTransitInventoryStateList(),
+ # start_date = {'query':now,'range':'max'},
+ # stop_date = {'query':now,'range':'min'},
+ default_destination_reference=user_name)]
+ # Now we can look directly at acknowledgement document not approved yet
+ # so not in a final state
+ final_state_list = self.getPortalCurrentInventoryStateList()
+ query = NegatedQuery(Query(simulation_state=final_state_list))
+ all_document_list.extend([x for x in \
+ self.portal_catalog(portal_type = portal_type,
+ query=query,
+ # start_date = {'query':now,'range':'max'},
+ # stop_date = {'query':now,'range':'min'},
+ destination_reference=user_name)])
+ for document in all_document_list:
+ # We filter manually on dates until a good solution is found for
+ # searching by dates on the catalog
+ if (document.getStartDate() < now < (document.getStopDate()+1)):
+ acknowledged = document.isAcknowledged(user_name=user_name)
+ if not acknowledged:
+ document_list.append(document.getRelativeUrl())
+ else:
+ raise ValueError('No user name given')
+ return document_list
+
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'acknowledge')
+ def acknowledge(self, uid=None, path=None, user_name=None, **kw):
+ """
+ Create an acknowledgement document for :
+ - a ticket
+ - an event
+ - an acknowledgement
+
+ This methods needs to check if there is already ongoing ackowledgement
+ for the document of for this user. We will have to use activities with
+ tag and probably a serialization.
+ """
+ document = None
+ if uid is not None:
+ document = self.portal_catalog.getObject(uid)
+ elif path is not None:
+ document = self.restrictedTraverse(path)
+ else:
+ raise ValueError("No path or uid given")
+ if document is None:
+ raise ValueError("Ticket does not exist or you don't have access to it")
+ return document.acknowledge(user_name=user_name, **kw)
+
+
+InitializeClass(AcknowledgementTool)
Modified: erp5/trunk/products/ERP5/__init__.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/__init__.py?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/__init__.py [utf8] (original)
+++ erp5/trunk/products/ERP5/__init__.py [utf8] Wed May 27 17:19:12 2009
@@ -47,7 +47,8 @@
from Tool import CategoryTool, SimulationTool, RuleTool, IdTool, TemplateTool,\
TestTool, DomainTool, AlarmTool, OrderTool, DeliveryTool,\
TrashTool, ContributionTool, NotificationTool, PasswordTool,\
- GadgetTool, ContributionRegistryTool, IntrospectionTool
+ GadgetTool, ContributionRegistryTool, IntrospectionTool,\
+ AcknowledgementTool
import ERP5Site
object_classes = ( ERP5Site.ERP5Site,
)
@@ -68,6 +69,7 @@
GadgetTool.GadgetTool,
ContributionRegistryTool.ContributionRegistryTool,
IntrospectionTool.IntrospectionTool,
+ AcknowledgementTool.AcknowledgementTool,
)
content_classes = ()
content_constructors = ()
Added: erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/bulletin_board.xml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/bulletin_board.xml?rev=27216&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/bulletin_board.xml (added)
+++ erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/bulletin_board.xml [utf8] Wed May 27 17:19:12 2009
@@ -1,0 +1,79 @@
+<?xml version="1.0"?>
+<ZopeData>
+ <record id="1" aka="AAAAAAAAAAE=">
+ <pickle>
+ <tuple>
+ <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+ <tuple/>
+ </tuple>
+ </pickle>
+ <pickle>
+ <dictionary>
+ <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_subpath</string> </key>
+ <value> <string>traverse_subpath</string> </value>
+ </item>
+ </dictionary>
+ </value>
+ </item>
+ </dictionary>
+ </state>
+ </object>
+ </value>
+ </item>
+ <item>
+ <key> <string>_text</string> </key>
+ <value> <string encoding="cdata"><![CDATA[
+
+<tal:block xmlns:tal="http://xml.zope.org/namespaces/tal"\n
+ xmlns:metal="http://xml.zope.org/namespaces/metal"\n
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n">\n
+ <tal:block metal:define-macro="master">\n
+ <tal:block tal:repeat="item here/AcknowledgementTool_getUserUnreadAcknowledgementList | nothing">\n
+ <div class="dialog_box">\n
+ <div class="list_dialog">\n
+ <tal:div content="structure item/text_content" />\n
+ </div>\n
+ <a tal:attributes="href item/acknowledge_url"><button>DISMISS</button></a>\n
+ </div>\n
+ </tal:block>\n
+ </tal:block>\n
+</tal:block>\n
+
+
+]]></string> </value>
+ </item>
+ <item>
+ <key> <string>content_type</string> </key>
+ <value> <string>text/html</string> </value>
+ </item>
+ <item>
+ <key> <string>expand</string> </key>
+ <value> <int>0</int> </value>
+ </item>
+ <item>
+ <key> <string>id</string> </key>
+ <value> <string>bulletin_board</string> </value>
+ </item>
+ <item>
+ <key> <string>title</string> </key>
+ <value> <string></string> </value>
+ </item>
+ </dictionary>
+ </pickle>
+ </record>
+</ZopeData>
Modified: erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/template_erp5_xhtml_style.xml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/template_erp5_xhtml_style.xml?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/template_erp5_xhtml_style.xml [utf8] (original)
+++ erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/template_erp5_xhtml_style.xml [utf8] Wed May 27 17:19:12 2009
@@ -129,6 +129,9 @@
</tal:block>\n
</div>\n
<p class="clear"></p>\n
+ <div id="bulletin_board">\n
+ <div tal:content="structure here/bulletin_board"/>\n
+ </div>\n
<div tal:content="request/portal_status_message | nothing" id="transition_message" />\n
<div id="information_area" tal:condition="request/field_errors | nothing"\n
i18n:translate="" i18n:domain="ui">\n
Modified: erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/bt/revision
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/bt/revision?rev=27216&r1=27215&r2=27216&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/bt/revision [utf8] (original)
+++ erp5/trunk/products/ERP5/bootstrap/erp5_xhtml_style/bt/revision [utf8] Wed May 27 17:19:12 2009
@@ -1,1 +1,1 @@
-760
+761
Added: erp5/trunk/products/ERP5/tests/testAcknowledgementTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/tests/testAcknowledgementTool.py?rev=27216&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/tests/testAcknowledgementTool.py (added)
+++ erp5/trunk/products/ERP5/tests/testAcknowledgementTool.py [utf8] Wed May 27 17:19:12 2009
@@ -1,0 +1,118 @@
+##############################################################################
+# -*- coding: utf8 -*-
+# Copyright (c) 2007 Nexedi SA and Contributors. All Rights Reserved.
+# Sebastien Robin <seb at nexedi.com>
+#
+# 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.
+#
+##############################################################################
+
+import unittest
+from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
+import transaction
+from DateTime import DateTime
+
+class TestAcknowledgementTool(ERP5TypeTestCase):
+
+ def getTitle(self):
+ return "AcknowledgementTool"
+
+ def getBusinessTemplateList(self):
+ return ('erp5_base',
+ 'erp5_crm',)
+
+ def test_01_checkAcknowledgementToolWithOneEvent(self):
+ """
+ Create an event of type site message, post it and check that the
+ acknowledgement tool is able to see it
+ """
+ event_type = "Site Message"
+ portal = self.getPortalObject()
+ module = portal.getDefaultModule(event_type)
+ event = module.newContent(portal_type=event_type)
+ person_module = portal.getDefaultModule('Person')
+ person = person_module.newContent(portal_type='Person', title='Seb',
+ reference='seb')
+ now = DateTime()
+ event.edit(destination_value=person,
+ text_content="A Nice Message",
+ text_format="text/plain",
+ title="foo",
+ start_date = now-2,
+ stop_date = now+2)
+ portal.portal_workflow.doActionFor(event, 'start_action')
+ self.assertEqual(event.getSimulationState(), 'started')
+ transaction.commit()
+ self.tic()
+
+ acknowledgement_tool_kw = {}
+ acknowledgement_tool_kw['user_name'] = 'seb'
+ acknowledgement_tool_kw['portal_type'] = event_type
+ document_url_list = portal.portal_acknowledgements\
+ .getUnreadDocumentUrlList(**acknowledgement_tool_kw)
+ self.assertTrue(event.getRelativeUrl() in document_url_list)
+
+ # function in order to retrieve many times the list of acknowledgements
+ def getEventAcknowlegementList():
+ acknowledgement_list = portal.portal_acknowledgements\
+ .getUnreadAcknowledgementList(
+ **acknowledgement_tool_kw)
+ event_acknowledgement_list = [x for x in acknowledgement_list
+ if x.getCausality() == event.getRelativeUrl()]
+ return event_acknowledgement_list
+
+ # We should have unread acknowledgement
+ event_acknowledgement_list = getEventAcknowlegementList()
+ self.assertEqual(1, len(event_acknowledgement_list))
+
+ # Check that the content is retrieved on the original event
+ event_acknowledgement = event_acknowledgement_list[0]
+ self.assertEqual(event_acknowledgement.getTextContent(), "A Nice Message")
+
+ # We know acknowledge the event
+ acknowledgement = portal.portal_acknowledgements.acknowledge(
+ path=event.getRelativeUrl(),
+ user_name='seb')
+ # Make sure that we have a new acknowledge document wich is a proxy of
+ # the event
+ self.assertEqual(acknowledgement.getPortalType(), 'Acknowledgement')
+ self.assertEqual(acknowledgement.getTextContent(), "A Nice Message")
+ transaction.commit()
+
+ # We should not have any acknowledgements, we just commited previous
+ # transaction, this means that we look if the mechanism that looks at
+ # activity tags is working or not
+ event_acknowledgement_list = getEventAcknowlegementList()
+ # We should not have any acknowledgements, tic is finished
+ # the code should look directly for acnowledgement documents
+ self.tic()
+ event_acknowledgement_list = getEventAcknowlegementList()
+ self.assertEqual(0, len(event_acknowledgement_list))
+
+ # We should have one acknowledgement in the event module
+
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestAcknowledgementTool))
+ return suite
More information about the Erp5-report
mailing list