Sanjay Gohel (Open ERP) has proposed merging 
lp:~openerp-dev/openobject-addons/trunk-tracked-fields-chs into 
lp:openobject-addons.

Requested reviews:
  Thibault Delavallée (OpenERP) (tde-openerp)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-tracked-fields-chs/+merge/138647

Hello,

      I have added tracked_field.rst for documentation on tracked field.

Thank You.
Sanjay Gohel
(SGO)
-- 
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-tracked-fields-chs/+merge/138647
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openobject-addons/trunk-tracked-fields-chs.
=== modified file 'account/account_invoice.py'
--- account/account_invoice.py	2012-12-05 11:28:53 +0000
+++ account/account_invoice.py	2012-12-07 07:23:20 +0000
@@ -207,7 +207,7 @@
             ('open','Open'),
             ('paid','Paid'),
             ('cancel','Cancelled'),
-            ],'Status', select=True, readonly=True,
+            ],'Status', select=True, readonly=True,tracked=True,
             help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed Invoice. \
             \n* The \'Pro-forma\' when invoice is in Pro-forma status,invoice does not have an invoice number. \
             \n* The \'Open\' status is used when user create invoice,a invoice number is generated.Its in open status till user does not pay invoice. \
@@ -275,7 +275,7 @@
             help="Remaining amount due."),
         'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'),
         'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}),
-        'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, states={'draft':[('readonly',False)]}),
+        'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, tracked=True, states={'draft':[('readonly',False)]}),
         'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]})
     }
     _defaults = {

=== modified file 'crm/crm.py'
--- crm/crm.py	2012-11-29 22:26:45 +0000
+++ crm/crm.py	2012-12-07 07:23:20 +0000
@@ -78,6 +78,7 @@
         'state': fields.selection(AVAILABLE_STATES, 'Related Status', required=True,
             help="The status of your document will automatically change regarding the selected stage. " \
                 "For example, if a stage is related to the status 'Close', when your document reaches this stage, it is automatically closed."),
+        'subtype': fields.char('Related Subtype', size=64),
         'case_default': fields.boolean('Common to All Teams',
                         help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
         'fold': fields.boolean('Hide in Views when Empty',

=== modified file 'crm/crm_lead.py'
--- crm/crm_lead.py	2012-12-05 13:37:23 +0000
+++ crm/crm_lead.py	2012-12-07 07:23:20 +0000
@@ -197,7 +197,7 @@
         'date_action_next': fields.datetime('Next Action', readonly=1),
         'email_from': fields.char('Email', size=128, help="Email address of the contact", select=1),
         'section_id': fields.many2one('crm.case.section', 'Sales Team', \
-                        select=True, help='When sending mails, the default email address is taken from the sales team.'),
+                        select=True, tracked=True, help='When sending mails, the default email address is taken from the sales team.'),
         'create_date': fields.datetime('Creation Date' , readonly=True),
         'email_cc': fields.text('Global CC', size=252 , help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
         'description': fields.text('Notes'),
@@ -213,9 +213,9 @@
         'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"),
         'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
         'date_closed': fields.datetime('Closed', readonly=True),
-        'stage_id': fields.many2one('crm.case.stage', 'Stage',
+        'stage_id': fields.many2one('crm.case.stage', 'Stage',tracked=True,
                         domain="['&', ('fold', '=', False), '&', '|', ('section_ids', '=', section_id), ('case_default', '=', True), '|', ('type', '=', type), ('type', '=', 'both')]"),
-        'user_id': fields.many2one('res.users', 'Salesperson'),
+        'user_id': fields.many2one('res.users', 'Salesperson',tracked=True),
         'referred': fields.char('Referred By', size=64),
         'date_open': fields.datetime('Opened', readonly=True),
         'day_open': fields.function(_compute_day, string='Days to Open', \
@@ -228,7 +228,7 @@
 
         # Only used for type opportunity
         'probability': fields.float('Success Rate (%)',group_operator="avg"),
-        'planned_revenue': fields.float('Expected Revenue'),
+        'planned_revenue': fields.float('Expected Revenue',tracked=True),
         'ref': fields.reference('Reference', selection=crm._links_get, size=128),
         'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
         'phone': fields.char("Phone", size=64),
@@ -386,7 +386,6 @@
             stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0)], context=context)
             if stage_id:
                 self.case_set(cr, uid, [lead.id], values_to_update={'probability': 0.0}, new_stage_id=stage_id, context=context)
-        self.case_mark_lost_send_note(cr, uid, ids, context=context)
         return True
 
     def case_mark_won(self, cr, uid, ids, context=None):
@@ -395,7 +394,6 @@
             stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0)], context=context)
             if stage_id:
                 self.case_set(cr, uid, [lead.id], values_to_update={'probability': 100.0}, new_stage_id=stage_id, context=context)
-        self.case_mark_won_send_note(cr, uid, ids, context=context)
         return True
 
     def set_priority(self, cr, uid, ids, priority):
@@ -847,11 +845,6 @@
     # OpenChatter methods and notifications
     # ----------------------------------------
 
-    def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
-        """ Override of the (void) default notification method. """
-        stage_name = self.pool.get('crm.case.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
-        return self.message_post(cr, uid, ids, body=_("Stage changed to <b>%s</b>.") % (stage_name), subtype="mt_crm_stage", context=context)
-
     def case_get_note_msg_prefix(self, cr, uid, lead, context=None):
         if isinstance(lead, (int, long)):
             lead = self.browse(cr, uid, [lead], context=context)[0]
@@ -863,14 +856,6 @@
             self.message_post(cr, uid, [id], body=message, context=context)
         return True
 
-    def case_mark_lost_send_note(self, cr, uid, ids, context=None):
-        message = _("Opportunity has been <b>lost</b>.")
-        return self.message_post(cr, uid, ids, body=message, subtype="mt_crm_lost", context=context)
-
-    def case_mark_won_send_note(self, cr, uid, ids, context=None):
-        message = _("Opportunity has been <b>won</b>.")
-        return self.message_post(cr, uid, ids, body=message, subtype="mt_crm_won", context=context)
-
     def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None):
         phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0]
         if action == 'log': prefix = 'Logged'

=== modified file 'crm/crm_lead_data.xml'
--- crm/crm_lead_data.xml	2012-11-29 22:26:45 +0000
+++ crm/crm_lead_data.xml	2012-12-07 07:23:20 +0000
@@ -7,6 +7,7 @@
             <field name="name">New</field>
             <field eval="1" name="case_default"/>
             <field name="state">draft</field>
+            <field name="subtype">mail.mt_crm_stage</field>
             <field eval="'10'" name="probability"/>
             <field eval="'10'" name="sequence"/>
             <field name="type">both</field>
@@ -15,6 +16,7 @@
             <field name="name">Opportunity</field>
             <field eval="1" name="case_default"/>
             <field name="state">open</field>
+            <field name="subtype">mail.mt_crm_stage</field>
             <field eval="'20'" name="probability"/>
             <field eval="'11'" name="sequence"/>
             <field name="type">lead</field>
@@ -23,6 +25,7 @@
             <field name="name">Qualification</field>
             <field eval="1" name="case_default"/>
             <field name="state">open</field>
+            <field name="subtype">mail.mt_crm_stage</field>
             <field eval="'20'" name="probability"/>
             <field eval="'12'" name="sequence"/>
             <field name="type">opportunity</field>
@@ -31,6 +34,7 @@
             <field name="name">Proposition</field>
             <field eval="1" name="case_default"/>
             <field name="state">open</field>
+            <field name="subtype">mail.mt_crm_stage</field>
             <field eval="'40'" name="probability"/>
             <field eval="'13'" name="sequence"/>
             <field name="type">opportunity</field>
@@ -39,6 +43,7 @@
             <field name="name">Negotiation</field>
             <field eval="1" name="case_default"/>
             <field name="state">open</field>
+            <field name="subtype">mail.mt_crm_stage</field>
             <field eval="'60'" name="probability"/>
             <field eval="'14'" name="sequence"/>
             <field name="type">opportunity</field>
@@ -47,6 +52,7 @@
             <field name="name">Won</field>
             <field eval="1" name="case_default"/>
             <field name="state">done</field>
+            <field name="subtype">mail.mt_crm_won</field>
             <field eval="'100'" name="probability"/>
             <field eval="'15'" name="sequence"/>
             <field eval="1" name="on_change"/>
@@ -57,6 +63,7 @@
             <field eval="1" name="case_default"/>
             <field eval="False" name="fold"/>
             <field name="state">cancel</field>
+            <field name="subtype">mail.mt_crm_stage</field>
             <field eval="'0'" name="probability"/>
             <field eval="'16'" name="sequence"/>
             <field name="type">lead</field>
@@ -66,6 +73,7 @@
             <field eval="1" name="case_default"/>
             <field eval="True" name="fold"/>
             <field name="state">cancel</field>
+            <field name="subtype">mail.mt_crm_lost</field>
             <field eval="'0'" name="probability"/>
             <field eval="'17'" name="sequence"/>
             <field name="type">opportunity</field>

=== modified file 'crm/crm_view.xml'
--- crm/crm_view.xml	2012-11-29 22:26:45 +0000
+++ crm/crm_view.xml	2012-12-07 07:23:20 +0000
@@ -203,6 +203,7 @@
                     <group col="4">
                         <field name="name"/>
                         <field name="state"/>
+                        <field name="subtype"/>
                         <field name="probability"/>
                         <field name="type"/>
                         <field name="on_change"/>

=== modified file 'crm/res_partner.py'
--- crm/res_partner.py	2012-11-29 22:26:45 +0000
+++ crm/res_partner.py	2012-12-07 07:23:20 +0000
@@ -39,7 +39,7 @@
         return res
 
     _columns = {
-        'section_id': fields.many2one('crm.case.section', 'Sales Team'),
+        'section_id': fields.many2one('crm.case.section', 'Sales Team',tracked=True),
         'opportunity_ids': fields.one2many('crm.lead', 'partner_id',\
             'Leads and Opportunities', domain=[('state','in', ('draft','open','pending'))]),
         'meeting_ids': fields.many2many('crm.meeting', 'crm_meeting_partner_rel','partner_id', 'meeting_id',

=== modified file 'hr_recruitment/hr_recruitment.py'
--- hr_recruitment/hr_recruitment.py	2012-11-30 17:11:30 +0000
+++ hr_recruitment/hr_recruitment.py	2012-12-07 07:23:20 +0000
@@ -186,7 +186,7 @@
         'partner_id': fields.many2one('res.partner', 'Contact'),
         'create_date': fields.datetime('Creation Date', readonly=True, select=True),
         'write_date': fields.datetime('Update Date', readonly=True),
-        'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage',
+        'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage',tracked=True,
                         domain="['&', ('fold', '=', False), '|', ('department_id', '=', department_id), ('department_id', '=', False)]"),
         'state': fields.related('stage_id', 'state', type="selection", store=True,
                 selection=AVAILABLE_STATES, string="Status", readonly=True,
@@ -197,7 +197,7 @@
                       set to \'Pending\'.'),
         'categ_ids': fields.many2many('hr.applicant_category', string='Tags'),
         'company_id': fields.many2one('res.company', 'Company'),
-        'user_id': fields.many2one('res.users', 'Responsible'),
+        'user_id': fields.many2one('res.users', 'Responsible',tracked=True),
         # Applicant Columns
         'date_closed': fields.datetime('Closed', readonly=True, select=True),
         'date_open': fields.datetime('Opened', readonly=True, select=True),

=== added file 'mail/doc/tracked_field.rst'
--- mail/doc/tracked_field.rst	1970-01-01 00:00:00 +0000
+++ mail/doc/tracked_field.rst	2012-12-07 07:23:20 +0000
@@ -0,0 +1,18 @@
+Tracked fields
+---------------
+Tracked fields is generic logging system for the changes applied to some fields in open chatter.
+ - In the definition of a fields. you have to simply add tracked=True.
+ - When changing one of the fields having tracked=True on saved automatically write a log in openchatter for the changes in fields.
+
+How it works:
++++++++++++++
+ - You have to add tracked=True in field defination as following.
+ - ``'stage_id': fields.many2one('project.task.type', 'Stage',tracked=True),``
+ - For developed this feature we override write method of mail_thread. 
+ - And make one mako template which shows old field and updated field.
+ 
+Open chatter log:
++++++++++++++++++
+ - After changing field follower can show log of tracked field in open chatter as followed.
+     - Updated Fields:
+           - Stage: Analysis -> Specification
\ No newline at end of file

=== modified file 'mail/mail_thread.py'
--- mail/mail_thread.py	2012-11-29 22:26:45 +0000
+++ mail/mail_thread.py	2012-12-07 07:23:20 +0000
@@ -20,19 +20,25 @@
 ##############################################################################
 
 import base64
+from collections import defaultdict
 import dateutil
 import email
+from functools import partial
 import logging
 import pytz
 import time
 import tools
 import xmlrpclib
 
+from mako.template import Template as MakoTemplate
+
 from email.message import Message
 from mail_message import decode
 from openerp import SUPERUSER_ID
 from osv import osv, fields
+from openerp.osv.orm import browse_record
 from tools.safe_eval import safe_eval as eval
+from tools.translate import _
 
 _logger = logging.getLogger(__name__)
 
@@ -68,6 +74,14 @@
     _name = 'mail.thread'
     _description = 'Email Thread'
     _mail_flat_thread = True
+    _TRACK_TEMPLATE = """
+        <span>${updated_fields}</span>
+        <ul>
+        %for chg in changes:
+            <li><span>${chg[0]}</span>: ${chg[1]} -> ${chg[2]}</li>
+        %endfor
+        </ul>
+    """
 
     def _get_message_data(self, cr, uid, ids, name, args, context=None):
         """ Computes:
@@ -250,6 +264,87 @@
         return super(mail_thread, self).copy(cr, uid, id, default=default, context=context)
 
     #------------------------------------------------------
+    # Automatically log tracked fields
+    #------------------------------------------------------
+
+    def write(self, cr, uid, ids, values, context=None):
+        
+        if context is None:
+            context = {}
+        #import pudb;pudb.set_trace()
+
+        def false_value(f):
+            if f._type == 'boolean':
+                return False
+            return f._symbol_set[1](False)
+
+        def convert_for_comparison(v, f):
+            # It will convert value for comparison between current and new.
+            if not v:
+                return false_value(f)
+            if isinstance(v, browse_record):
+                return v.id
+            return v
+
+        tracked = dict((n, f) for n, f in self._all_columns.items() if getattr(f.column, 'tracked', False))
+        to_log = [k for k in values if k in tracked]
+
+        from_ = None
+        changes = defaultdict(list)
+        if to_log:
+            for record in self.browse(cr, uid, ids, context):
+                for tl in to_log:
+                    column = tracked[tl].column
+                    current = convert_for_comparison(record[tl], column)
+                    new = convert_for_comparison(values[tl], column)
+                    if new != current:
+                        changes[record].append(tl)
+                        from_ = record[tl]
+
+        result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
+
+        updated_fields = _('Updated Fields:')
+
+        Trans = self.pool['ir.translation']
+        def _t(c):
+            # translate field
+            model = c.parent_model or self._name
+            lang = context.get('lang')
+            return Trans._get_source(cr, uid, '{0},{1}'.format(model, c.name), 'field', lang, ci.column.string)
+        
+        def get_subtype(model, record):
+            # it will return subtype name(xml_id) for stage.
+            record_model = self.pool[model].browse(cr, SUPERUSER_ID, record)
+            if record_model.__hasattr__('subtype'):
+                return record_model.subtype
+            return False 
+
+        for record, changed_fields in changes.items():
+            # TODO tpl changed_fields
+            chg = []
+            subtype = False
+            for f in changed_fields:
+                to = self.browse(cr, uid, ids[0], context)[f]
+                ci = tracked[f]
+                if ci.column._type == "many2one":
+                    if to:
+                        to = to.name_get()[0][1]
+                    else:
+                        to = "Removed"
+                    if isinstance(from_, browse_record):
+                        from_ = from_.name_get()[0][1]
+                    
+                    subtype = get_subtype(ci.column._obj,values[f])
+                chg.append((_t(ci), from_, to))
+
+            message = MakoTemplate(self._TRACK_TEMPLATE).render_unicode(updated_fields=updated_fields,
+                                                                        changes=chg)
+
+            record.message_post(message,subtype=subtype)
+
+        return result
+
+    #------------------------------------------------------
     # mail.message wrappers and tools
     #------------------------------------------------------
 

=== modified file 'project/project.py'
--- project/project.py	2012-11-30 17:11:30 +0000
+++ project/project.py	2012-12-07 07:23:20 +0000
@@ -46,6 +46,7 @@
         'state': fields.selection(_TASK_STATE, 'Related Status', required=True,
                         help="The status of your document is automatically changed regarding the selected stage. " \
                             "For example, if a stage is related to the status 'Close', when your document reaches this stage, it is automatically closed."),
+        'subtype': fields.char('Related Subtype', size=64),
         'fold': fields.boolean('Hide in views if empty',
                         help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
     }
@@ -750,7 +751,7 @@
         'description': fields.text('Description'),
         'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True),
         'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."),
-        'stage_id': fields.many2one('project.task.type', 'Stage',
+        'stage_id': fields.many2one('project.task.type', 'Stage',tracked=True,
                         domain="['&', ('fold', '=', False), ('project_ids', '=', project_id)]"),
         'state': fields.related('stage_id', 'state', type="selection", store=True,
                 selection=_TASK_STATE, string="Status", readonly=True,
@@ -770,7 +771,7 @@
         'date_start': fields.datetime('Starting Date',select=True),
         'date_end': fields.datetime('Ending Date',select=True),
         'date_deadline': fields.date('Deadline',select=True),
-        'project_id': fields.many2one('project.project', 'Project', ondelete='set null', select="1"),
+        'project_id': fields.many2one('project.project', 'Project', ondelete='set null', select="1",tracked=True),
         'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'),
         'child_ids': fields.many2many('project.task', 'project_task_parent_rel', 'parent_id', 'task_id', 'Delegated Tasks'),
         'notes': fields.text('Notes'),
@@ -796,7 +797,7 @@
                 'project.task': (lambda self, cr, uid, ids, c={}: ids, ['work_ids', 'remaining_hours', 'planned_hours'], 10),
                 'project.task.work': (_get_task, ['hours'], 10),
             }),
-        'user_id': fields.many2one('res.users', 'Assigned to'),
+        'user_id': fields.many2one('res.users', 'Assigned to',tracked=True),
         'delegated_user_id': fields.related('child_ids', 'user_id', type='many2one', relation='res.users', string='Delegated To'),
         'partner_id': fields.many2one('res.partner', 'Customer'),
         'work_ids': fields.one2many('project.task.work', 'task_id', 'Work done'),
@@ -991,14 +992,12 @@
             if not task.date_end:
                 vals['date_end'] = fields.datetime.now()
             self.case_set(cr, uid, [task.id], 'done', vals, context=context)
-            self.case_close_send_note(cr, uid, [task.id], context=context)
         return True
 
     def do_reopen(self, cr, uid, ids, context=None):
         for task in self.browse(cr, uid, ids, context=context):
             project = task.project_id
             self.case_set(cr, uid, [task.id], 'open', {}, context=context)
-            self.case_open_send_note(cr, uid, [task.id], context)
         return True
 
     def do_cancel(self, cr, uid, ids, context=None):
@@ -1010,7 +1009,6 @@
         self._check_child_task(cr, uid, ids, context=context)
         for task in tasks:
             self.case_set(cr, uid, [task.id], 'cancelled', {'remaining_hours': 0.0}, context=context)
-            self.case_cancel_send_note(cr, uid, [task.id], context=context)
         return True
 
     def do_open(self, cr, uid, ids, context=None):
@@ -1020,7 +1018,6 @@
     def case_open(self, cr, uid, ids, context=None):
         if not isinstance(ids,list): ids = [ids]
         self.case_set(cr, uid, ids, 'open', {'date_start': fields.datetime.now()}, context=context)
-        self.case_open_send_note(cr, uid, ids, context)
         return True
 
     def do_draft(self, cr, uid, ids, context=None):
@@ -1029,7 +1026,6 @@
 
     def case_draft(self, cr, uid, ids, context=None):
         self.case_set(cr, uid, ids, 'draft', {}, context=context)
-        self.case_draft_send_note(cr, uid, ids, context=context)
         return True
 
     def do_pending(self, cr, uid, ids, context=None):
@@ -1037,8 +1033,7 @@
         return self.case_pending(cr, uid, ids, context=context)
 
     def case_pending(self, cr, uid, ids, context=None):
-        self.case_set(cr, uid, ids, 'pending', {}, context=context)
-        return self.case_pending_send_note(cr, uid, ids, context=context)
+        return self.case_set(cr, uid, ids, 'pending', {}, context=context)
 
     def _delegate_task_attachments(self, cr, uid, task_id, delegated_task_id, context=None):
         attachment = self.pool.get('ir.attachment')
@@ -1078,7 +1073,6 @@
                 self.do_pending(cr, uid, [task.id], context=context)
             elif delegate_data['state'] == 'done':
                 self.do_close(cr, uid, [task.id], context=context)
-            self.do_delegation_send_note(cr, uid, [task.id], context)
             delegated_tasks[task.id] = delegated_task_id
         return delegated_tasks
 
@@ -1158,7 +1152,6 @@
         self._subscribe_project_followers_to_task(cr, uid, task_id, context=context)
 
         self._store_history(cr, uid, [task_id], context=context)
-        self.create_send_note(cr, uid, [task_id], context=context)
         return task_id
 
     # Overridden to reset the kanban_state to normal whenever
@@ -1176,7 +1169,6 @@
                     #raise osv.except_osv(_('Warning!'), _('Stage is not defined in the project.'))
                 write_vals = vals_reset_kstate if t.stage_id != new_stage else vals
                 super(task, self).write(cr, uid, [t.id], write_vals, context=context)
-                self.stage_set_send_note(cr, uid, [t.id], new_stage, context=context)
             result = True
         else:
             result = super(task, self).write(cr, uid, ids, vals, context=context)
@@ -1286,24 +1278,8 @@
         res = super(task, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
         return res + ['user_id', 'manager_id']
 
-    def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
-        """ Override of the (void) default notification method. """
-        stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
-        return self.message_post(cr, uid, ids, body=_("Stage changed to <b>%s</b>.") % (stage_name),
-            context=context)
-
-    def create_send_note(self, cr, uid, ids, context=None):
-        return self.message_post(cr, uid, ids, body=_("Task has been <b>created</b>."), context=context)
-
-    def case_draft_send_note(self, cr, uid, ids, context=None):
         return self.message_post(cr, uid, ids, body=_('Task has been set as <b>draft</b>.'), context=context)
 
-    def do_delegation_send_note(self, cr, uid, ids, context=None):
-        for task in self.browse(cr, uid, ids, context=context):
-            msg = _('Task has been <b>delegated</b> to <em>%s</em>.') % (task.user_id.name)
-            self.message_post(cr, uid, [task.id], body=msg, context=context)
-        return True
-   
     def project_task_reevaluate(self, cr, uid, ids, context=None):
         if self.pool.get('res.users').has_group(cr, uid, 'project.group_time_work_estimation_tasks'):
             return {

=== modified file 'project/project_data.xml'
--- project/project_data.xml	2012-11-29 22:26:45 +0000
+++ project/project_data.xml	2012-12-07 07:23:20 +0000
@@ -30,11 +30,13 @@
             <field name="sequence">1</field>
             <field name="name">Analysis</field>
             <field name="state">draft</field>
+            <field name="subtype">project.mt_task_new</field>
             <field name="case_default" eval="False"/>
         </record>
         <record id="project_tt_specification" model="project.task.type">
             <field name="sequence">2</field>
             <field name="name">Specification</field>
+            <field name="subtype">project.mt_task_change</field>
             <field name="state">pending</field>
             <field name="case_default" eval="True"/>
         </record>
@@ -42,11 +44,13 @@
             <field name="sequence">2</field>
             <field name="name">Design</field>
             <field name="state">open</field>
+            <field name="subtype">project.mt_task_change</field>
             <field name="case_default" eval="True"/>
         </record>
         <record id="project_tt_development" model="project.task.type">
             <field name="sequence">3</field>
             <field name="name">Development</field>
+            <field name="subtype">project.mt_task_change</field>
             <field name="state">open</field>
             <field name="case_default" eval="True"/>
         </record>
@@ -54,12 +58,14 @@
             <field name="sequence">4</field>
             <field name="name">Testing</field>
             <field name="state">open</field>
+            <field name="subtype">project.mt_task_change</field>
             <field name="case_default" eval="True"/>
         </record>
         <record id="project_tt_merge" model="project.task.type">
             <field name="sequence">5</field>
             <field name="name">Merge</field>
             <field name="state">open</field>
+            <field name="subtype">project.mt_task_change</field>
             <field name="case_default" eval="False"/>
             <field name="fold" eval="True"/>
         </record>
@@ -67,6 +73,7 @@
             <field name="sequence">6</field>
             <field name="name">Done</field>
             <field name="state">done</field>
+            <field name="subtype">project.mt_task_closed</field>
             <field name="case_default" eval="True"/>
             <field name="fold" eval="True"/>
         </record>
@@ -74,6 +81,7 @@
             <field name="sequence">7</field>
             <field name="name">Cancelled</field>
             <field name="state">cancelled</field>
+            <field name="subtype">project.mt_task_canceled</field>
             <field name="case_default" eval="True"/>
             <field name="fold" eval="True"/>
         </record>

=== modified file 'project/project_view.xml'
--- project/project_view.xml	2012-11-29 22:26:45 +0000
+++ project/project_view.xml	2012-12-07 07:23:20 +0000
@@ -748,6 +748,7 @@
                         </group>
                         <group>
                             <field name="state"/>
+                            <field name="subtype"/>
                             <field name="sequence"/>
                             <field name="fold"/>
                         </group>

=== modified file 'project_issue/project_issue.py'
--- project_issue/project_issue.py	2012-11-29 22:26:45 +0000
+++ project_issue/project_issue.py	2012-12-07 07:23:20 +0000
@@ -245,14 +245,14 @@
         'version_id': fields.many2one('project.issue.version', 'Version'),
         'stage_id': fields.many2one ('project.task.type', 'Stage',
                         domain="['&', ('fold', '=', False), ('project_ids', '=', project_id)]"),
-        'project_id':fields.many2one('project.project', 'Project'),
+        'project_id':fields.many2one('project.project', 'Project',tracked=True),
         'duration': fields.float('Duration'),
         'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"),
         'day_open': fields.function(_compute_day, string='Days to Open', \
                                 multi='compute_day', type="float", store=True),
         'day_close': fields.function(_compute_day, string='Days to Close', \
                                 multi='compute_day', type="float", store=True),
-        'user_id': fields.many2one('res.users', 'Assigned to', required=False, select=1),
+        'user_id': fields.many2one('res.users', 'Assigned to', required=False, select=1,tracked=True),
         'working_hours_open': fields.function(_compute_day, string='Working Hours to Open the Issue', \
                                 multi='compute_day', type="float", store=True),
         'working_hours_close': fields.function(_compute_day, string='Working Hours to Close the Issue', \

=== modified file 'sale/sale.py'
--- sale/sale.py	2012-12-04 14:46:49 +0000
+++ sale/sale.py	2012-12-07 07:23:20 +0000
@@ -187,7 +187,7 @@
             ('manual', 'Sale to Invoice'),
             ('invoice_except', 'Invoice Exception'),
             ('done', 'Done'),
-            ], 'Status', readonly=True, help="Gives the status of the quotation or sales order. \nThe exception status is automatically set when a cancel operation occurs in the processing of a document linked to the sale order. \nThe 'Waiting Schedule' status is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
+            ], 'Status', readonly=True, tracked=True, help="Gives the status of the quotation or sales order. \nThe exception status is automatically set when a cancel operation occurs in the processing of a document linked to the sale order. \nThe 'Waiting Schedule' status is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
         'date_order': fields.date('Date', required=True, readonly=True, select=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
         'create_date': fields.datetime('Creation Date', readonly=True, select=True, help="Date on which sales order is created."),
         'date_confirm': fields.date('Confirmation Date', readonly=True, select=True, help="Date on which sales order is confirmed."),

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : openerp-dev-gtk@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to