diff --git a/product/CMFActivity/ActiveObject.py b/product/CMFActivity/ActiveObject.py
index 171834b4482ae574fdfc3312c16516b04e2b4db6..1b9e90ecf1eefabc40e627847f9e32fba0f11ece 100755
--- a/product/CMFActivity/ActiveObject.py
+++ b/product/CMFActivity/ActiveObject.py
@@ -76,6 +76,10 @@ class ActiveObject(ExtensionClass.Base):
     # a queue can be provided as well as extra parameters
     # which can be used for example to define deferred tasks
     try:
+      # This volatile variable '_v_activate_kw' can be used to pass parameters
+      # automatically to activate.
+      if hasattr(self, '_v_activate_kw'):
+        kw.update(self._v_activate_kw)
       return activity_tool.activate(self, activity, active_process, **kw)
     except ConflictError:
       raise
diff --git a/product/CMFActivity/Activity/SQLDict.py b/product/CMFActivity/Activity/SQLDict.py
index 42c0d1eb8db6cf9eb3b9caee10c3b87541c5dce1..e7dd61ccaa0735482bb1082b5943466351df7c21 100755
--- a/product/CMFActivity/Activity/SQLDict.py
+++ b/product/CMFActivity/Activity/SQLDict.py
@@ -69,7 +69,8 @@ class SQLDict(RAMDict):
                                           broadcast = m.activity_kw.get('broadcast', 0),
                                           message = self.dumpMessage(m),
                                           date = m.activity_kw.get('at_date', DateTime()),
-                                          group_method_id = m.activity_kw.get('group_method_id', ''))
+                                          group_method_id = m.activity_kw.get('group_method_id', ''),
+                                          tag = m.activity_kw.get('tag', ''))
                                           # Also store uid of activity
 
   def prepareQueueMessageList(self, activity_tool, message_list):
@@ -87,13 +88,15 @@ class SQLDict(RAMDict):
       datetime = DateTime()
       date_list = [message.activity_kw.get('at_date', datetime) for message in registered_message_list]
       group_method_id_list = [message.activity_kw.get('group_method_id', '') for message in registered_message_list]
+      tag_list = [message.activity_kw.get('tag', '') for message in registered_message_list]
       activity_tool.SQLDict_writeMessageList( path_list = path_list,
                                               method_id_list = method_id_list,
                                               priority_list = priority_list,
                                               broadcast_list = broadcast_list,
                                               message_list = dumped_message_list,
                                               date_list = date_list,
-                                              group_method_id_list = group_method_id_list)
+                                              group_method_id_list = group_method_id_list,
+                                              tag_list = tag_list)
                                                          
   def prepareDeleteMessage(self, activity_tool, m):
     # Erase all messages in a single transaction
@@ -465,6 +468,31 @@ class SQLDict(RAMDict):
       return INVALID_ORDER
     return VALID
 
+  def _validate_after_tag(self, activity_tool, message, value):
+    # Count number of occurances of tag
+    if type(value) == type(''):
+      value = [value]
+    result = activity_tool.SQLDict_validateMessageList(method_id=None, message_uid=None, tag=value)
+    if result[0].uid_count > 0:
+      return INVALID_ORDER
+    return VALID
+    
+  def _validate_after_tag_and_method_id(self, activity_tool, message, value):
+    # Count number of occurances of tag and method_id
+    if (type(value) != type ( (0,) ) and type(value) != type([])) or len(value)<2:
+      LOG('CMFActivity WARNING :', 0, 'unable to recognize value for after_tag_and_method_id : %s' % repr(value))
+      return VALID
+    tag = value[0]
+    method = value[1]
+    if type(tag) == type(''):
+      tag = [tag]
+    if type(method) == type(''):
+      method = [method]
+    result = activity_tool.SQLDict_validateMessageList(method_id=method, message_uid=None, tag=tag)
+    if result[0].uid_count > 0:
+      return INVALID_ORDER
+    return VALID
+
   # Required for tests (time shift)
   def timeShift(self, activity_tool, delay):
     """
diff --git a/product/CMFActivity/Activity/SQLQueue.py b/product/CMFActivity/Activity/SQLQueue.py
index 5b1a1ea925a430cbbf57add88f5a1656b03ae518..54e6c643bf7fbdfbf5eb7a0dc7b801ee9258b9f4 100755
--- a/product/CMFActivity/Activity/SQLQueue.py
+++ b/product/CMFActivity/Activity/SQLQueue.py
@@ -66,7 +66,8 @@ class SQLQueue(RAMQueue):
                                           priority = m.activity_kw.get('priority', 1),
                                           broadcast = m.activity_kw.get('broadcast', 0),
                                           message = self.dumpMessage(m),
-                                          date = m.activity_kw.get('at_date', DateTime()))
+                                          date = m.activity_kw.get('at_date', DateTime()),
+                                          tag = m.activity_kw.get('tag', ''))
 
   def prepareDeleteMessage(self, activity_tool, m):
     # Erase all messages in a single transaction
@@ -286,6 +287,31 @@ class SQLQueue(RAMQueue):
     if result[0].uid_count > 0:
       return INVALID_ORDER
     return VALID
+    
+  def _validate_after_tag(self, activity_tool, message, value):
+    # Count number of occurances of tag
+    if type(value) == type(''):
+      value = [value]
+    result = activity_tool.SQLQueue_validateMessageList(method_id=None, message_uid=None, tag=value)
+    if result[0].uid_count > 0:
+      return INVALID_ORDER
+    return VALID
+    
+  def _validate_after_tag_and_method_id(self, activity_tool, message, value):
+    # Count number of occurances of tag and method_id
+    if (type(value) != type ( (0,) ) and type(value) != type([])) or len(value)<2:
+      LOG('CMFActivity WARNING :', 0, 'unable to recognize value for after_tag_and_method_id : %s' % repr(value))
+      return VALID
+    tag = value[0]
+    method = value[1]
+    if type(tag) == type(''):
+      tag = [tag]
+    if type(method) == type(''):
+      method = [method]
+    result = activity_tool.SQLQueue_validateMessageList(method_id=method, message_uid=None, tag=tag)
+    if result[0].uid_count > 0:
+      return INVALID_ORDER
+    return VALID
   
   # Required for tests (time shift)
   def timeShift(self, activity_tool, delay):
diff --git a/product/CMFActivity/skins/activity/SQLDict_createMessageTable.zsql b/product/CMFActivity/skins/activity/SQLDict_createMessageTable.zsql
index 3d3baf09f9919288c13dacb4c2d848a7a1154c39..cc2ab582ec4cc5aceb21dcf4591084074eed2d14 100755
--- a/product/CMFActivity/skins/activity/SQLDict_createMessageTable.zsql
+++ b/product/CMFActivity/skins/activity/SQLDict_createMessageTable.zsql
@@ -19,6 +19,7 @@ CREATE TABLE `message` (
   `priority` TINYINT DEFAULT 0,
   `broadcast` TINYINT DEFAULT 0,
   `group_method_id` VARCHAR(255) DEFAULT '',
+  `tag` VARCHAR(255),
   `message` BLOB,
   PRIMARY KEY  (`uid`),
   KEY `date` (`date`),
@@ -27,5 +28,6 @@ CREATE TABLE `message` (
   KEY `processing_node` (`processing_node`),
   KEY `processing` (`processing`),
   KEY `processing_date` (`processing_date`),
-  KEY `priority` (`priority`)
+  KEY `priority` (`priority`),
+  KEY `tag` (`tag`)
 ) TYPE = InnoDB;
diff --git a/product/CMFActivity/skins/activity/SQLDict_validateMessageList.zsql b/product/CMFActivity/skins/activity/SQLDict_validateMessageList.zsql
index 4c79317be907e5229b423e02cfcd063b87d131d3..3f8ac6d4915055079ed188ab18ce8c29c956acb5 100755
--- a/product/CMFActivity/skins/activity/SQLDict_validateMessageList.zsql
+++ b/product/CMFActivity/skins/activity/SQLDict_validateMessageList.zsql
@@ -10,6 +10,7 @@ class_file:
 <params>method_id
 message_uid
 path
+tag
 </params>
 SELECT
     COUNT(DISTINCT uid) as uid_count
@@ -32,3 +33,10 @@ WHERE
 </dtml-in>
     )
 </dtml-if>
+<dtml-if tag>
+    AND (
+<dtml-in tag>
+        tag = <dtml-sqlvar sequence-item type="string"><dtml-if sequence-end><dtml-else> OR </dtml-if>
+</dtml-in>
+    )
+</dtml-if>
diff --git a/product/CMFActivity/skins/activity/SQLDict_writeMessage.zsql b/product/CMFActivity/skins/activity/SQLDict_writeMessage.zsql
index 52a1d2de3817446d0f74334cba0109d0308061c1..1f72be1907a2e5608a0df417eb7311e636a87cc5 100755
--- a/product/CMFActivity/skins/activity/SQLDict_writeMessage.zsql
+++ b/product/CMFActivity/skins/activity/SQLDict_writeMessage.zsql
@@ -14,7 +14,8 @@ priority
 broadcast
 date
 processing_node=-1
-group_method_id</params>
+group_method_id
+tag</params>
 INSERT INTO message
 SET
   path = <dtml-sqlvar path type="string">,
@@ -25,4 +26,5 @@ SET
   priority = <dtml-sqlvar priority type="int">,
   broadcast = <dtml-sqlvar broadcast type="int">,
   group_method_id = <dtml-sqlvar group_method_id type="string">,
+  tag = <dtml-sqlvar tag type="string">,
   message = <dtml-sqlvar message type="string">
diff --git a/product/CMFActivity/skins/activity/SQLDict_writeMessageList.zsql b/product/CMFActivity/skins/activity/SQLDict_writeMessageList.zsql
index 66a81a85f23a78178c5d4c30a7a0ea24df2ecd3d..17a9b38cc34df71bf30961b88aa80a871ae4f6f2 100755
--- a/product/CMFActivity/skins/activity/SQLDict_writeMessageList.zsql
+++ b/product/CMFActivity/skins/activity/SQLDict_writeMessageList.zsql
@@ -14,9 +14,10 @@ priority_list
 broadcast_list
 date_list
 processing_node_list
-group_method_id_list</params>
+group_method_id_list
+tag_list</params>
 INSERT INTO message
-(path, date, method_id, processing_node, processing, priority, broadcast, group_method_id, message)
+(path, date, method_id, processing_node, processing, priority, broadcast, group_method_id, tag, message)
 VALUES
 <dtml-in prefix="loop" expr="_.range(_.len(path_list))">
 <dtml-if sequence-start><dtml-else>,</dtml-if>
@@ -29,6 +30,7 @@ VALUES
   <dtml-sqlvar expr="priority_list[loop_item]" type="int">,
   <dtml-sqlvar expr="broadcast_list[loop_item]" type="int">,
   <dtml-sqlvar expr="group_method_id_list[loop_item]" type="string">,
+  <dtml-sqlvar expr="tag_list[loop_item]" type="string">,
   <dtml-sqlvar expr="message_list[loop_item]" type="string">
 )
 </dtml-in>
diff --git a/product/CMFActivity/skins/activity/SQLQueue_createMessageTable.zsql b/product/CMFActivity/skins/activity/SQLQueue_createMessageTable.zsql
index 20a88e99a6346c964c678c062a223ed39471d85f..6d00582520937c4d15e0a55659be6ff5aeabb9a9 100755
--- a/product/CMFActivity/skins/activity/SQLQueue_createMessageTable.zsql
+++ b/product/CMFActivity/skins/activity/SQLQueue_createMessageTable.zsql
@@ -18,6 +18,7 @@ CREATE TABLE `message_queue` (
   `processing_date` datetime,
   `priority` INT DEFAULT 0,
   `broadcast` INT DEFAULT 0,
+  `tag` VARCHAR(255),
   `message` BLOB,
   PRIMARY KEY  (`uid`),
   KEY `date` (`date`),
@@ -26,5 +27,6 @@ CREATE TABLE `message_queue` (
   KEY `processing_node` (`processing_node`),
   KEY `processing` (`processing`),
   KEY `processing_date` (`processing_date`),
-  KEY `priority` (`priority`)
+  KEY `priority` (`priority`),
+  KEY `tag` (`tag`)
 ) TYPE = InnoDB;
diff --git a/product/CMFActivity/skins/activity/SQLQueue_validateMessageList.zsql b/product/CMFActivity/skins/activity/SQLQueue_validateMessageList.zsql
index 13c2207e4e67713d446632b87d17e7784368b201..9fc103e8d2de01789fc99e52b2e102398b740c59 100755
--- a/product/CMFActivity/skins/activity/SQLQueue_validateMessageList.zsql
+++ b/product/CMFActivity/skins/activity/SQLQueue_validateMessageList.zsql
@@ -10,6 +10,7 @@ class_file:
 <params>method_id
 message_uid
 path
+tag
 </params>
 SELECT
     COUNT(DISTINCT uid) as uid_count
@@ -32,3 +33,10 @@ WHERE
 </dtml-in>
     )
 </dtml-if>
+<dtml-if tag>
+    AND (
+<dtml-in tag>
+        tag = <dtml-sqlvar sequence-item type="string"><dtml-if sequence-end><dtml-else> OR </dtml-if>
+</dtml-in>
+    )
+</dtml-if>
diff --git a/product/CMFActivity/skins/activity/SQLQueue_writeMessage.zsql b/product/CMFActivity/skins/activity/SQLQueue_writeMessage.zsql
index a782c2b1e514eef82caf16b967e83a05b8823071..56bcb9b537fea047b683e2bddfd532c104616861 100755
--- a/product/CMFActivity/skins/activity/SQLQueue_writeMessage.zsql
+++ b/product/CMFActivity/skins/activity/SQLQueue_writeMessage.zsql
@@ -13,7 +13,8 @@ message
 priority
 broadcast
 processing_node=-1
-date</params>
+date
+tag</params>
 INSERT INTO message_queue
 SET
 	path = <dtml-sqlvar path type="string">,
@@ -23,4 +24,5 @@ SET
 	broadcast = <dtml-sqlvar broadcast type="int">,
 	processing = -1,
 	priority = <dtml-sqlvar priority type="int">,
+	tag = <dtml-sqlvar tag type="string">,
 	message = <dtml-sqlvar message type="string">
diff --git a/product/CMFActivity/tests/testCMFActivity.py b/product/CMFActivity/tests/testCMFActivity.py
index 01f3abff0ba4aa05a91bda4684bd802ef86df32a..f15a95a29f52da28613f23d56edd08a31f55485c 100755
--- a/product/CMFActivity/tests/testCMFActivity.py
+++ b/product/CMFActivity/tests/testCMFActivity.py
@@ -546,6 +546,37 @@ class TestCMFActivity(ERP5TypeTestCase):
     message_list = portal.portal_activities.getMessageList()
     self.assertEquals(len(message_list),1)
 
+  def TryAfterTag(self, activity):
+    """
+      Ensure the order of an execution by a tag
+    """
+    portal = self.getPortal()
+    organisation_module = self.getOrganisationModule()
+    if not organisation_module.hasContent(self.company_id):
+      organisation_module.newContent(id=self.company_id)
+    o = portal.organisation._getOb(self.company_id)
+    
+    o.setTitle('?')
+    self.assertEquals(o.getTitle(), '?')
+    get_transaction().commit()
+    self.tic()
+    
+    o.activate(after_tag = 'toto', activity = activity).setTitle('b')
+    o.activate(tag = 'toto', activity = activity).setTitle('a')
+    get_transaction().commit()
+    self.tic()
+    self.assertEquals(o.getTitle(), 'b')
+    
+    o._v_activate_kw = {'tag':'toto'}
+    def titi(self):
+      self.setCorporateName(self.getTitle() + 'd')
+    o.__class__.titi = titi
+    o.activate(after_tag_and_method_id=('toto', 'setTitle'), activity = activity).titi()
+    o.activate(activity = activity).setTitle('c')
+    get_transaction().commit()
+    self.tic()
+    self.assertEquals(o.getCorporateName(), 'cd')
+    
   def test_01_DeferedSetTitleSQLDict(self, quiet=0, run=run_all_test):
     # Test if we can add a complete sales order
     if not run: return
@@ -1088,6 +1119,25 @@ class TestCMFActivity(ERP5TypeTestCase):
       LOG('Testing... ',0,message)
     self.ExpandedMethodWithDeletedObject('SQLDict')
 
+  def test_59_TryAfterTagWithSQLDict(self, quiet=0, run=run_all_test):
+    # Test if after_tag can be used
+    if not run: return
+    if not quiet:
+      message = '\nTry After Tag With SQL Dict'
+      ZopeTestCase._print(message)
+      LOG('Testing... ',0,message)
+    self.TryAfterTag('SQLDict')
+
+  def test_60_TryAfterTagWithSQLDict(self, quiet=0, run=run_all_test):
+    # Test if after_tag can be used
+    if not run: return
+    if not quiet:
+      message = '\nTry After Tag With SQL Queue'
+      ZopeTestCase._print(message)
+      LOG('Testing... ',0,message)
+    self.TryAfterTag('SQLQueue')
+
+
 if __name__ == '__main__':
     framework()
 else: