[IMP] mail: added auto_follow mechanism on fields like 'user_id'. mail.thread defines a basic heuristic to find those tracked fields: fields called 'user_id', linking to res_users, that are tracked. This allows to automatically subscribe the responsible of main models in OpenERP, like opportunity, task, issue, applicant. This revision also sets some subtypes as not followed by default to avoid leaking information (for example when changing state of a recruitment with the applicant automatically added as follower).
bzr revid: tde@openerp.com-20130130145834-e5lr8h36xozavr7f
This commit is contained in:
commit
0dc0b1c08a
|
@ -155,11 +155,13 @@
|
|||
<record id="mt_invoice_validated" model="mail.message.subtype">
|
||||
<field name="name">Validated</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Invoice validated</field>
|
||||
</record>
|
||||
<record id="mt_invoice_paid" model="mail.message.subtype">
|
||||
<field name="name">Paid</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Invoice paid</field>
|
||||
</record>
|
||||
</data>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<record id="mt_voucher_state_change" model="mail.message.subtype">
|
||||
<field name="name">Status Change</field>
|
||||
<field name="res_model">account.voucher</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Status changed</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -6,16 +6,19 @@
|
|||
<record id="mt_account_pending" model="mail.message.subtype">
|
||||
<field name="name">Contract to Renew</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Contract pending</field>
|
||||
</record>
|
||||
<record id="mt_account_closed" model="mail.message.subtype">
|
||||
<field name="name">Contract Finished</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Contract closed</field>
|
||||
</record>
|
||||
<record id="mt_account_opened" model="mail.message.subtype">
|
||||
<field name="name">Contract Opened</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Contract opened</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -171,11 +171,13 @@
|
|||
<record id="mt_lead_stage" model="mail.message.subtype">
|
||||
<field name="name">Stage Changed</field>
|
||||
<field name="res_model">crm.lead</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Stage changed</field>
|
||||
</record>
|
||||
<record id="mt_lead_won" model="mail.message.subtype">
|
||||
<field name="name">Opportunity Won</field>
|
||||
<field name="res_model">crm.lead</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Opportunity won</field>
|
||||
</record>
|
||||
<record id="mt_lead_lost" model="mail.message.subtype">
|
||||
|
|
|
@ -470,11 +470,13 @@
|
|||
<record id="mt_stage_changed" model="mail.message.subtype">
|
||||
<field name="name">Stage Changed</field>
|
||||
<field name="res_model">hr.applicant</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Stage changed</field>
|
||||
</record>
|
||||
<record id="mt_applicant_hired" model="mail.message.subtype">
|
||||
<field name="name">Applicant Hired</field>
|
||||
<field name="res_model">hr.applicant</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Applicant hired</field>
|
||||
</record>
|
||||
<record id="mt_applicant_refused" model="mail.message.subtype">
|
||||
|
|
|
@ -243,7 +243,7 @@ class mail_thread(osv.AbstractModel):
|
|||
# subscribe uid unless asked not to
|
||||
if not context.get('mail_create_nosubscribe'):
|
||||
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
|
||||
self.message_subscribe_from_parent(cr, uid, [thread_id], values.keys(), context=context)
|
||||
self.message_auto_subscribe(cr, uid, [thread_id], values.keys(), context=context)
|
||||
|
||||
# automatic logging unless asked not to (mainly for various testing purpose)
|
||||
if not context.get('mail_create_nolog'):
|
||||
|
@ -261,7 +261,7 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
# Perform write, update followers
|
||||
result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
|
||||
self.message_subscribe_from_parent(cr, uid, ids, values.keys(), context=context)
|
||||
self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context)
|
||||
|
||||
# Perform the tracking
|
||||
if tracked_fields:
|
||||
|
@ -1069,7 +1069,24 @@ class mail_thread(osv.AbstractModel):
|
|||
self.check_access_rights(cr, uid, 'write')
|
||||
return self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context)
|
||||
|
||||
def message_subscribe_from_parent(self, cr, uid, ids, updated_fields, context=None):
|
||||
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
|
||||
""" Returns the list of relational fields linking to res.users that should
|
||||
trigger an auto subscribe. The default list checks for the fields
|
||||
- called 'user_id'
|
||||
- linking to res.users
|
||||
- with track_visibility set
|
||||
In OpenERP V7, this is sufficent for all major addon such as opportunity,
|
||||
project, issue, recruitment, sale.
|
||||
Override this method if a custom behavior is needed about fields
|
||||
that automatically subscribe users.
|
||||
"""
|
||||
user_field_lst = []
|
||||
for name, column_info in self._all_columns.items():
|
||||
if name in auto_follow_fields and name in updated_fields and getattr(column_info.column, 'track_visibility', False) and column_info.column._obj == 'res.users':
|
||||
user_field_lst.append(name)
|
||||
return user_field_lst
|
||||
|
||||
def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None):
|
||||
"""
|
||||
1. fetch project subtype related to task (parent_id.res_model = 'project.task')
|
||||
2. for each project subtype: subscribe the follower to the task
|
||||
|
@ -1077,13 +1094,16 @@ class mail_thread(osv.AbstractModel):
|
|||
subtype_obj = self.pool.get('mail.message.subtype')
|
||||
follower_obj = self.pool.get('mail.followers')
|
||||
|
||||
# fetch auto_follow_fields
|
||||
user_field_lst = self._message_get_auto_subscribe_fields(cr, uid, updated_fields, context=context)
|
||||
|
||||
# fetch related record subtypes
|
||||
related_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)], context=context)
|
||||
subtypes = subtype_obj.browse(cr, uid, related_subtype_ids, context=context)
|
||||
default_subtypes = [subtype for subtype in subtypes if subtype.res_model == False]
|
||||
related_subtypes = [subtype for subtype in subtypes if subtype.res_model != False]
|
||||
relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field != False])
|
||||
if not related_subtypes or not any(relation in updated_fields for relation in relation_fields):
|
||||
if (not related_subtypes or not any(relation in updated_fields for relation in relation_fields)) and not user_field_lst:
|
||||
return True
|
||||
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -1105,20 +1125,24 @@ class mail_thread(osv.AbstractModel):
|
|||
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context):
|
||||
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.parent_id.id)
|
||||
|
||||
if not parent_res_id or not parent_model:
|
||||
continue
|
||||
if parent_res_id and parent_model:
|
||||
for subtype in default_subtypes:
|
||||
follower_ids = follower_obj.search(cr, SUPERUSER_ID, [
|
||||
('res_model', '=', parent_model),
|
||||
('res_id', '=', parent_res_id),
|
||||
('subtype_ids', 'in', [subtype.id])
|
||||
], context=context)
|
||||
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context):
|
||||
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.id)
|
||||
|
||||
for subtype in default_subtypes:
|
||||
follower_ids = follower_obj.search(cr, SUPERUSER_ID, [
|
||||
('res_model', '=', parent_model),
|
||||
('res_id', '=', parent_res_id),
|
||||
('subtype_ids', 'in', [subtype.id])
|
||||
], context=context)
|
||||
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context):
|
||||
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.id)
|
||||
# add followers coming from res.users relational fields that are tracked
|
||||
user_ids = [getattr(record, name).id for name in user_field_lst if getattr(record, name)]
|
||||
for partner_id in [user.partner_id.id for user in self.pool.get('res.users').browse(cr, SUPERUSER_ID, user_ids, context=context)]:
|
||||
new_followers.setdefault(partner_id, None)
|
||||
|
||||
for pid, subtypes in new_followers.items():
|
||||
self.message_subscribe(cr, uid, [record.id], [pid], list(subtypes), context=context)
|
||||
subtypes = list(subtypes) if subtypes is not None else None
|
||||
self.message_subscribe(cr, uid, [record.id], [pid], subtypes, context=context)
|
||||
return True
|
||||
|
||||
#------------------------------------------------------
|
||||
|
|
|
@ -94,16 +94,19 @@
|
|||
<record id="mt_task_blocked" model="mail.message.subtype">
|
||||
<field name="name">Task Blocked</field>
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Task blocked</field>
|
||||
</record>
|
||||
<record id="mt_task_closed" model="mail.message.subtype">
|
||||
<field name="name">Task Done</field>
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Task closed</field>
|
||||
</record>
|
||||
<record id="mt_task_stage" model="mail.message.subtype">
|
||||
<field name="name">Stage Changed</field>
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Stage changed</field>
|
||||
</record>
|
||||
<!-- Project-related subtypes for messaging / Chatter -->
|
||||
|
|
|
@ -59,16 +59,19 @@ Access all issues from the top Project menu, and access the issues of a specific
|
|||
<record id="mt_issue_blocked" model="mail.message.subtype">
|
||||
<field name="name">Issue Blocked</field>
|
||||
<field name="res_model">project.issue</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Issue blocked</field>
|
||||
</record>
|
||||
<record id="mt_issue_closed" model="mail.message.subtype">
|
||||
<field name="name">Issue Closed</field>
|
||||
<field name="res_model">project.issue</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Issue closed</field>
|
||||
</record>
|
||||
<record id="mt_issue_stage" model="mail.message.subtype">
|
||||
<field name="name">Stage Changed</field>
|
||||
<field name="res_model">project.issue</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Stage changed</field>
|
||||
</record>
|
||||
<!-- Project-related subtypes for messaging / Chatter -->
|
||||
|
|
|
@ -52,10 +52,12 @@
|
|||
<!-- Purchase-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_rfq_confirmed" model="mail.message.subtype">
|
||||
<field name="name">RFQ Confirmed</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="res_model">purchase.order</field>
|
||||
</record>
|
||||
<record id="mt_rfq_approved" model="mail.message.subtype">
|
||||
<field name="name">RFQ Approved</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="res_model">purchase.order</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -48,11 +48,13 @@
|
|||
<record id="mt_order_sent" model="mail.message.subtype">
|
||||
<field name="name">Quotation send</field>
|
||||
<field name="res_model">sale.order</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Quotation send</field>
|
||||
</record>
|
||||
<record id="mt_order_confirmed" model="mail.message.subtype">
|
||||
<field name="name">Sales Order Confirmed</field>
|
||||
<field name="res_model">sale.order</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Quotation confirmed</field>
|
||||
</record>
|
||||
|
||||
|
|
Loading…
Reference in New Issue