[MERGE] Merged with feature branch holding mail-state, and some cleaning in mail.thread.

bzr revid: tde@openerp.com-20120605135912-8r5w1694mk81n12h
This commit is contained in:
Thibault Delavallée
2012-06-05 15:59:12 +02:00
16 changed files with 355 additions and 323 deletions
+56 -67
View File
@@ -262,11 +262,10 @@ class crm_lead(base_stage, osv.osv):
def get_needaction_user_ids(self, cr, uid, ids, context=None):
result = dict.fromkeys(ids, [])
for obj in self.browse(cr, uid, ids, context=context):
# salesman must perform an action when in draft mode
if obj.state == 'draft' and obj.user_id:
if obj.message_thread_read == False and obj.user_id:
result[obj.id] = [obj.user_id.id]
return result
def create(self, cr, uid, vals, context=None):
obj_id = super(crm_lead, self).create(cr, uid, vals, context)
self.create_send_note(cr, uid, [obj_id], context=context)
@@ -756,64 +755,6 @@ class crm_lead(base_stage, osv.osv):
'type': 'ir.actions.act_window',
}
def message_new(self, cr, uid, msg, custom_values=None, context=None):
"""Automatically calls when new email message arrives"""
res_id = super(crm_lead, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
subject = msg.get('subject') or _("No Subject")
body = msg.get('body_text')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if priority:
vals['priority'] = priority
vals.update(self.message_partner_by_email(cr, uid, msg.get('from', False)))
self.write(cr, uid, [res_id], vals, context)
return res_id
def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None):
if isinstance(ids, (str, int, long)):
ids = [ids]
if vals == None:
vals = {}
super(crm_lead, self).message_update(cr, uid, ids, msg, context=context)
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = {}
for line in msg['body_text'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
# Unfortunately the API is based on lists
# but we want to update the state based on the
# previous state, so we have to loop:
for case in self.browse(cr, uid, ids, context=context):
values = dict(vals)
if case.state in CRM_LEAD_PENDING_STATES:
#re-open
values.update(state=crm.AVAILABLE_STATES[1][0])
if not case.date_open:
values['date_open'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
res = self.write(cr, uid, [case.id], values, context=context)
return res
def action_makeMeeting(self, cr, uid, ids, context=None):
"""
This opens Meeting's calendar view to schedule meeting on current Opportunity
@@ -868,18 +809,66 @@ class crm_lead(base_stage, osv.osv):
if stage.on_change:
vals['probability'] = stage.probability
return super(crm_lead,self).write(cr, uid, ids, vals, context)
# ----------------------------------------
# Mail Gateway
# ----------------------------------------
def message_new(self, cr, uid, msg, custom_values=None, context=None):
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
'description': msg.get('body_text'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
})
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
custom_values['priority'] = msg.get('priority')
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from', False), context=context))
return super(crm_lead, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if update_vals is None: update_vals = {}
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability',
}
for line in msg.get('body_text', '').split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
vals[key] = res.group(2).lower()
return super(crm_lead, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
# ----------------------------------------
# OpenChatter methods and notifications
# ----------------------------------------
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(crm_lead, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add the salesman. """
user_ids = super(crm_lead, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
return super(crm_lead, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.user_id.id)
return user_ids
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]
+6
View File
@@ -70,11 +70,17 @@
states="cancel"/>
<button name="case_cancel" string="Cancel" type="object"
states="draft,open,pending"/>
<button name="message_mark_as_unread" string="Mark Unread" type="object"
attrs="{'invisible':[('message_thread_read', '==', False)]}"/>
<button name="message_mark_as_read" string="Mark Read" type="object"
attrs="{'invisible':[('message_thread_read', '==', True)]}"/>
<field name="stage_id" widget="statusbar"
on_change="onchange_stage_id(stage_id)"/>
</header>
<sheet layout="auto">
<group colspan="4" col="7">
<field name="message_thread_read"/>
<newline/>
<field name="name"/>
<field name="priority"/>
<field name="categ_id"
+30 -36
View File
@@ -183,59 +183,53 @@ class crm_claim(base_stage, osv.osv):
}
address = self.pool.get('res.partner').browse(cr, uid, part)
return {'value': {'email_from': address.email, 'partner_phone': address.phone}}
def message_new(self, cr, uid, msg, custom_values=None, context=None):
"""Automatically called when new email message arrives"""
res_id = super(crm_claim,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
subject = msg.get('subject')
body = msg.get('body_text')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if priority:
vals['priority'] = priority
vals.update(self.message_partner_by_email(cr, uid, msg.get('from', False)))
self.write(cr, uid, [res_id], vals, context=context)
return res_id
def message_update(self, cr, uid, ids, msg, vals={}, default_act='pending', context=None):
# -------------------------------------------------------
# Mail gateway
# -------------------------------------------------------
def message_new(self, cr, uid, msg, custom_values=None, context=None):
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
'description': msg.get('body_text'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
})
if msg.get('priority'):
custom_values['priority'] = msg.get('priority')
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from'), context=context))
return super(crm_claim,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
res_id = super(crm_claim,self).message_update(cr, uid, ids, msg, context=context)
if update_vals is None: update_vals = {}
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
vals['priority'] = msg.get('priority')
update_vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = {}
for line in msg['body_text'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
update_vals[key] = res.group(2).lower()
# Unfortunately the API is based on lists
# but we want to update the state based on the
# previous state, so we have to loop:
for case in self.browse(cr, uid, ids, context=context):
values = dict(vals)
if case.state in CRM_CLAIM_PENDING_STATES:
values.update(state=crm.AVAILABLE_STATES[1][0]) #re-open
res = self.write(cr, uid, [case.id], values, context=context)
return res
return super(crm_claim,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
# ---------------------------------------------------
# OpenChatter methods and notifications
+17 -12
View File
@@ -127,21 +127,26 @@ class crm_fundraising(base_stage, osv.osv):
self.create_send_note(cr, uid, [obj_id], context=context)
return obj_id
# -------------------------------------------------------
# Mail gateway
# -------------------------------------------------------
def message_new(self, cr, uid, msg, custom_values=None, context=None):
"""Automatically called when new email message arrives"""
res_id = super(crm_fundraising,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
vals = {
'name': msg.get('subject'),
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override also updates the document according to the email.
"""
if custom_values is None: custom_values = {}
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
'description': msg.get('body_text'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'description': msg.get('body_text'),
}
priority = msg.get('priority')
if priority:
vals['priority'] = priority
vals.update(self.message_partner_by_email(cr, uid, msg.get('from')))
self.write(cr, uid, [res_id], vals, context=context)
return res_id
})
if msg.get('priority'):
custom_values['priority'] = priority
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from'), context=context))
return super(crm_fundraising,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
# ---------------------------------------------------
# OpenChatter methods and notifications
+28 -32
View File
@@ -95,55 +95,51 @@ class crm_helpdesk(base_state, osv.osv):
self.create_send_note(cr, uid, [obj_id], context=context)
return obj_id
def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):
"""Automatically called when new email message arrives"""
res_id = super(crm_helpdesk,self).message_new(cr, uid, msg_dict, custom_values=custom_values, context=context)
subject = msg_dict.get('subject') or _("No Subject")
body = msg_dict.get('body_text')
msg_from = msg_dict.get('from')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg_dict.get('cc'),
'description': body,
'user_id': False,
}
vals.update(self.message_partner_by_email(cr, uid, msg_from))
self.write(cr, uid, [res_id], vals, context)
return res_id
# -------------------------------------------------------
# Mail gateway
# -------------------------------------------------------
def message_update(self, cr, uid, ids, msg, vals={}, default_act='pending', context=None):
def message_new(self, cr, uid, msg, custom_values=None, context=None):
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
'description': msg.get('body_text'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
})
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from'), context=context))
return super(crm_helpdesk,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
super(crm_helpdesk,self).message_update(cr, uid, ids, msg, context=context)
if update_vals is None: update_vals = {}
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
vals['priority'] = msg.get('priority')
update_vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = {}
for line in msg['body_text'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
update_vals[key] = res.group(2).lower()
# Unfortunately the API is based on lists
# but we want to update the state based on the
# previous state, so we have to loop:
for case in self.browse(cr, uid, ids, context=context):
values = dict(vals)
if case.state in CRM_HELPDESK_STATES:
values.update(state=crm.AVAILABLE_STATES[1][0]) #re-open
res = self.write(cr, uid, [case.id], values, context=context)
return res
return super(crm_helpdesk,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
# ******************************
# OpenChatter
+7 -6
View File
@@ -371,14 +371,15 @@ class hr_holidays(osv.osv):
result[obj.id] = hr_manager_group['users']
return result
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(hr_holidays, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add employee and its manager. """
user_ids = super(hr_holidays, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
if obj.employee_id.parent_id and not obj.employee_id.parent_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.employee_id.parent_id.id], context=context)
return super(hr_holidays, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.user_id.id)
if obj.employee_id.parent_id and not obj.employee_id.parent_id.user_id.id in user_ids:
user_ids.append(obj.employee_id.parent_id.user_id.id)
return user_ids
def create_notificate(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
+37 -37
View File
@@ -362,54 +362,53 @@ class hr_applicant(base_stage, osv.Model):
return value
def message_new(self, cr, uid, msg, custom_values=None, context=None):
"""Automatically called when new email message arrives"""
res_id = super(hr_applicant,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
subject = msg.get('subject') or _("No Subject")
body = msg.get('body_text')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
'description': msg.get('body_text'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if priority:
vals['priority'] = priority
vals.update(self.message_partner_by_email(cr, uid, msg.get('from', False)))
self.write(cr, uid, [res_id], vals, context)
return res_id
})
if msg.get('priority'):
custom_values['priority'] = msg.get('priority')
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from', False), context=context))
return super(hr_applicant,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None):
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Override mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if vals is None:
vals = {}
msg_from = msg['from']
vals.update({
'description': msg['body_text']
if update_vals is None: vals = {}
update_vals.update({
'description': msg.get('body'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
})
if msg.get('priority', False):
vals['priority'] = msg.get('priority')
if msg.get('priority'):
update_vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'cost': 'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
'probability': 'probability',
}
vls = { }
for line in msg['body_text'].split('\n'):
for line in msg.get('body_text', '').split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
update_vals[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals, context=context)
self.message_append_dict(cr, uid, ids, msg, context=context)
return res
return super(hr_applicant, self).message_update(cr, uids, ids, update_vals=update_vals, context=context)
def create(self, cr, uid, vals, context=None):
obj_id = super(hr_applicant, self).create(cr, uid, vals, context=context)
@@ -499,12 +498,13 @@ class hr_applicant(base_stage, osv.Model):
# OpenChatter methods and notifications
# -------------------------------------------------------
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(hr_applicant, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add responsible user. """
user_ids = super(hr_applicant, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
return super(hr_applicant, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.user_id.id)
return user_ids
def get_needaction_user_ids(self, cr, uid, ids, context=None):
result = dict.fromkeys(ids, [])
+1 -1
View File
@@ -81,7 +81,7 @@ class mail_group(osv.osv):
result = dict.fromkeys(ids)
for id in ids:
result[id] = {}
result[id]['member_ids'] = self.message_get_subscribers(cr, uid, [id], True, context=context)
result[id]['member_ids'] = self.message_get_subscribers(cr, uid, [id], context=context)
result[id]['member_count'] = len(result[id]['member_ids'])
result[id]['is_subscriber'] = uid in result[id]['member_ids']
return result
+80 -31
View File
@@ -34,7 +34,7 @@ import xmlrpclib
_logger = logging.getLogger(__name__)
class mail_thread(osv.osv):
class mail_thread(osv.Model):
'''Mixin model, meant to be inherited by any model that needs to
act as a discussion topic on which messages can be attached.
Public methods are prefixed with ``message_`` in order to avoid
@@ -71,7 +71,14 @@ class mail_thread(osv.osv):
# OpenChatter: message_ids is a dummy field that should not be used
_columns = {
'message_ids': fields.function(_get_message_ids, method=True,
type='one2many', obj='mail.message', string='Temp messages', _fields_id = 'res_id'),
type='one2many', obj='mail.message', string='Temp messages', _fields_id = 'res_id',
help="Functional field holding messages related to the current document."),
'message_thread_read': fields.boolean('Read',
help="When checked, new messages require your attention."),
}
_defaults = {
'message_thread_read': True,
}
#------------------------------------------------------
@@ -79,7 +86,7 @@ class mail_thread(osv.osv):
#------------------------------------------------------
def create(self, cr, uid, vals, context=None):
"""Automatically subscribe the creator"""
"""Automatically subscribe the creator """
thread_id = super(mail_thread, self).create(cr, uid, vals, context=context)
if thread_id:
self.message_subscribe(cr, uid, [thread_id], [uid], context=context)
@@ -118,7 +125,7 @@ class mail_thread(osv.osv):
#------------------------------------------------------
def message_create(self, cr, uid, thread_id, vals, context=None):
"""OpenChatter: wrapper of mail.message create method
""" OpenChatter: wrapper of mail.message create method
- creates the mail.message
- automatically subscribe the message writer
- push the message to subscribed users
@@ -563,7 +570,7 @@ class mail_thread(osv.osv):
if res_id:
res_id = res_id.group(1)
if res_id:
res_id = int(res_id)
res_id = res_id
if model_pool.exists(cr, uid, res_id):
if hasattr(model_pool, 'message_update'):
model_pool.message_update(cr, uid, [res_id], msg, {}, context=context)
@@ -572,8 +579,10 @@ class mail_thread(osv.osv):
res_id = False
if not res_id:
res_id = create_record(msg)
#To forward the email to other followers
# To forward the email to other followers
self.message_forward(cr, uid, model, [res_id], msg_txt, context=context)
# Set as Unread
model_pool.message_mark_as_unread(cr, uid, [res_id], context=context)
return res_id
def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):
@@ -608,29 +617,34 @@ class mail_thread(osv.osv):
fields = model_pool.fields_get(cr, uid, context=context)
data = model_pool.default_get(cr, uid, fields, context=context)
if 'name' in fields and not data.get('name'):
data['name'] = msg_dict.get('from','')
data['name'] = msg_dict.get('from', '')
if custom_values and isinstance(custom_values, dict):
data.update(custom_values)
res_id = model_pool.create(cr, uid, data, context=context)
self.message_append_dict(cr, uid, [res_id], msg_dict, context=context)
return res_id
def message_update(self, cr, uid, ids, msg_dict, vals={}, default_act=None, context=None):
"""Called by ``message_process`` when a new message is received
for an existing thread. The default behavior is to create a
new mail.message in the given thread (by calling
``message_append_dict``)
Additional behavior may be implemented by overriding this
method.
def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
""" Called by ``message_process`` when a new message is received
for an existing thread. The default behavior is to create a
new mail.message in the given thread (by calling
``message_append_dict``)
Additional behavior may be implemented by overriding this
method.
:param dict msg_dict: a map containing the email details and
:param dict msg_dict: a map containing the email details and
attachments. See ``message_process`` and
``mail.message.parse()`` for details.
:param dict context: if a ``thread_model`` value is present
:param dict vals: a dict containing values to update records
given their ids; if the dict is None or is
void, no write operation is performed.
:param dict context: if a ``thread_model`` value is present
in the context, its value will be used
to determine the model of the thread to
update (instead of the current model).
"""
if update_vals:
self.write(cr, uid, ids, update_vals, context=context)
return self.message_append_dict(cr, uid, ids, msg_dict, context=context)
def message_thread_followers(self, cr, uid, ids, context=None):
@@ -786,46 +800,70 @@ class mail_thread(osv.osv):
# Subscription mechanism
#------------------------------------------------------
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Returns the current document followers. Basically this method
checks in mail.subscription for entries with mathing res_model,
checks in mail.subscription for entries with matching res_model,
res_id.
:param get_ids: if set to True, return the ids of users; if set
to False, returns the result of a read in res.users
:param get_ids: if set to True, return the ids of users; if set
to False, returns the result of a read in res.users
"""
subscr_obj = self.pool.get('mail.subscription')
subscr_ids = subscr_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)], context=context)
user_ids = [sub['user_id'][0] for sub in subscr_obj.read(cr, uid, subscr_ids, ['user_id'], context=context)]
if get_ids:
return user_ids
else:
return self.pool.get('res.users').read(cr, uid, user_ids, fields=['id', 'name', 'avatar'], context=context)
return [sub['user_id'][0] for sub in subscr_obj.read(cr, uid, subscr_ids, ['user_id'], context=context)]
def message_read_subscribers(self, cr, uid, ids, fields=['id', 'name', 'avatar'], context=None):
""" Returns the current document followers as a read result. Used
mainly for Chatter having only one method to call to have
details about users.
"""
user_ids = self.message_get_subscribers(cr, uid, ids, context=context)
return self.pool.get('res.users').read(cr, uid, user_ids, fields=fields, context=context)
def message_is_subscriber(self, cr, uid, ids, user_id = None, context=None):
subscr_obj = self.pool.get('mail.subscription')
""" Check if uid or user_id (if set) is a subscriber to the current
document.
:param user_id: if set, check is done on user_id; if not set
check is done on uid
"""
sub_user_id = uid if user_id is None else user_id
return (subscr_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', '=', sub_user_id)], count=True, context=context) > 0)
if sub_user_id in self.message_get_subscribers(cr, uid, ids, context=context):
return True
return False
def message_subscribe(self, cr, uid, ids, user_ids = None, context=None):
""" Subscribe the user (or user_ids) to the current document.
:param user_ids: a list of user_ids; if not set, subscribe
uid instead
"""
subscription_obj = self.pool.get('mail.subscription')
to_subscribe_uids = [uid] if user_ids is None else user_ids
create_ids = []
for id in ids:
already_subscribed_user_ids = self.message_get_subscribers(cr, uid, [id], context=context)
for user_id in to_subscribe_uids:
if self.message_is_subscriber(cr, uid, [id], user_id=user_id, context=context): continue
if user_id in already_subscribed_user_ids: continue
create_ids.append(subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context))
return create_ids
def message_unsubscribe(self, cr, uid, ids, user_ids = None, context=None):
if not user_ids and not uid in self.message_get_subscribers(cr, uid, ids, True, context=context):
""" Unsubscribe the user (or user_ids) from the current document.
:param user_ids: a list of user_ids; if not set, subscribe
uid instead
"""
# Trying to unsubscribe somebody not in subscribers: returns False
# if special management is needed; allows to know that an automatically
# subscribed user tries to unsubscribe and allows to warn him
if not user_ids and not uid in self.message_get_subscribers(cr, uid, ids, context=context):
return False
subscription_obj = self.pool.get('mail.subscription')
to_unsubscribe_uids = [uid] if user_ids is None else user_ids
to_delete_sub_ids = subscription_obj.search(cr, uid,
['&', '&', ('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', 'in', to_unsubscribe_uids)], context=context)
subscription_obj.unlink(cr, uid, to_delete_sub_ids, context=context)
return True
return subscription_obj.unlink(cr, uid, to_delete_sub_ids, context=context)
def message_subscription_hide(self, cr, uid, ids, subtype=None, context=None):
"""Hide notifications, allowing to tune the messages displayed on
@@ -936,4 +974,15 @@ class mail_thread(osv.osv):
to_del_notif_ids = notif_obj.search(cr, uid, ['&', ('user_id', '=', uid), ('message_id', 'in', notif_msg_ids)], context=context)
return notif_obj.unlink(cr, uid, to_del_notif_ids, context=context)
#------------------------------------------------------
# Thread_state
#------------------------------------------------------
def message_mark_as_read(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'message_thread_read': True}, context=context)
def message_mark_as_unread(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'message_thread_read': False}, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+1 -1
View File
@@ -474,7 +474,7 @@ openerp.mail = function(session) {
},
fetch_subscribers: function () {
return this.ds.call('message_get_subscribers', [[this.view.datarecord.id]]).then(this.proxy('display_subscribers'));
return this.ds.call('message_read_subscribers', [[this.view.datarecord.id]]).then(this.proxy('display_subscribers'));
},
display_subscribers: function (records) {
+5 -4
View File
@@ -1041,12 +1041,13 @@ class mrp_production(osv.osv):
result[obj.id] = [obj.user_id.id]
return result
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(mrp_production, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add responsible user. """
user_ids = super(mrp_production, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
return super(mrp_production, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.user_id.id)
return user_ids
def create_send_note(self, cr, uid, ids, context=None):
self.message_append_note(cr, uid, ids, body=_("Manufacturing order has been <b>created</b>."), context=context)
+11 -9
View File
@@ -474,12 +474,13 @@ def Project():
result[obj.id] = [obj.user_id.id]
return result
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(project, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add responsible user. """
user_ids = super(project, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
return super(project, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.user_id.id)
return user_ids
def create(self, cr, uid, vals, context=None):
obj_id = super(project, self).create(cr, uid, vals, context=context)
@@ -1151,14 +1152,15 @@ class task(base_stage, osv.osv):
result[obj.id] = [obj.user_id.id]
return result
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(task, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add responsible user and project manager. """
user_ids = super(task, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
user_ids.append(obj.user_id.id)
if obj.manager_id and not obj.manager_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.manager_id.id], context=context)
return super(task, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.manager_id.id)
return user_ids
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
+42 -49
View File
@@ -467,69 +467,56 @@ class project_issue(base_stage, osv.osv):
# -------------------------------------------------------
def message_new(self, cr, uid, msg, custom_values=None, context=None):
"""Automatically called when new email message arrives"""
if context is None:
context = {}
subject = msg.get('subject') or _('No Title')
body = msg.get('body_text')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
if context is None: context = {}
context['state_to'] = 'draft'
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
'description': msg.get('body_text'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if priority:
vals['priority'] = priority
vals.update(self.message_partner_by_email(cr, uid, msg_from))
context.update({'state_to' : 'draft'})
})
if msg.get('priority'):
custom_values['priority'] = msg.get('priority')
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from'), context=context))
if custom_values and isinstance(custom_values, dict):
vals.update(custom_values)
res_id = self.create(cr, uid, vals, context)
self.message_append_dict(cr, uid, [res_id], msg, context=context)
res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
self.convert_to_bug(cr, uid, [res_id], context=context)
return res_id
def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None):
if vals is None:
vals = {}
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if update_vals is None: update_vals = {}
vals.update({
'description': msg['body_text']
})
if msg.get('priority', False):
vals['priority'] = msg.get('priority')
# Update doc values according to the message
update_vals['description'] = msg.get('body_text', '')
if msg.get('priority'):
update_vals['priority'] = msg.get('priority')
# Parse 'body_text' to find values to update
maps = {
'cost': 'planned_cost',
'revenue': 'planned_revenue',
'probability': 'probability'
'probability': 'probability',
}
# Reassign the 'open' state to the case if this one is in pending or done
for record in self.browse(cr, uid, ids, context=context):
if record.state in ('pending', 'done'):
self.case_set(cr, uid, ids, 'open', {}, context=context)
vls = { }
for line in msg['body_text'].split('\n'):
for line in msg.get('body_text', '').split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
update_vals[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals)
self.message_append_dict(cr, uid, ids, msg, context=context)
return res
return super(project_issue, self).message_update(cr, uid, ids, update_vals=update_vals, context=context)
# -------------------------------------------------------
# OpenChatter methods and notifications
@@ -542,12 +529,18 @@ class project_issue(base_stage, osv.osv):
result[obj.id] = [obj.user_id.id]
return result
def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
user_ids = super(project_issue, self).message_get_subscribers(cr, uid, ids, True, context=context)
def message_get_subscribers(self, cr, uid, ids, context=None):
""" Override to add responsible user. """
user_ids = super(project_issue, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
return super(project_issue, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
user_ids.append(obj.user_id.id)
return user_ids
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_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
""" Override of default prefix for notifications. """
+23 -20
View File
@@ -19,30 +19,35 @@
#
##############################################################################
import binascii
from osv import fields, osv
from tools.translate import _
import tools
import binascii
class project_tasks(osv.osv):
_inherit = 'project.task'
def message_new(self, cr, uid, msg, custom_values=None, context=None):
res_id = super(project_tasks,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
subject = msg.get('subject')
msg_from = msg.get('from')
data = {
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
custom_values.update({
'name': subject,
'planned_hours': 0.0,
}
data.update(self.message_partner_by_email(cr, uid, msg_from))
self.write(cr, uid, [res_id], data, context)
return res_id
def message_update(self, cr, uid, ids, msg, data={}, default_act='pending'):
act = 'do_'+default_act
'subject': msg.get('subject'),
})
custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from', False), context=context))
return super(project_tasks,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the task according to the email.
"""
if update_vals is None: update_vals = {}
act = False
maps = {
'cost':'planned_hours',
}
@@ -54,17 +59,15 @@ class project_tasks(osv.osv):
field = maps.get(match)
if field:
try:
data[field] = float(res.group(2).lower())
update_vals[field] = float(res.group(2).lower())
except (ValueError, TypeError):
pass
elif match.lower() == 'state' \
and res.group(2).lower() in ['cancel','close','draft','open','pending']:
act = 'do_%s' % res.group(2).lower()
self.write(cr, uid, ids, data, context=context)
getattr(self,act)(cr, uid, ids, context=context)
self.message_append_note(cr, uid, [res_id], body=msg, context=context)
return True
if act:
getattr(self,act)(cr, uid, ids, context=context)
return super(project_tasks,self).message_update(cr, uid, msg, update_vals=update_vals, context=context)
def message_thread_followers(self, cr, uid, ids, context=None):
followers = super(project_tasks,self).message_thread_followers(cr, uid, ids, context=context)
@@ -74,5 +77,5 @@ class project_tasks(osv.osv):
followers[task.id] = filter(None, task_followers)
return followers
project_tasks()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+8 -13
View File
@@ -135,6 +135,7 @@
</group>
<notebook colspan="5">
<page string="Sales Order">
<group col="4">
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="[('customer','=',True)]" context="{'search_default_customer':1}" />
<field domain="[('parent_id','=',partner_id)]" name="partner_invoice_id" groups="sale.group_delivery_invoice_address" options='{"quick_create": false}'/>
<field domain="[('parent_id','=',partner_id)]" name="partner_shipping_id" groups="sale.group_delivery_invoice_address" options='{"quick_create": false}'/>
@@ -211,23 +212,17 @@
<field name="price_subtotal" groups="base.group_sale_notes_subtotal"/>
</tree>
</field>
<group colspan="2" col="4" name="bellow_the_lines_hook">
<group colspan="3" col="4" name="bellow_the_lines_hook">
</group>
<group class="oe_form_subtotal_footer" colspan="1" col="2">
<field name="amount_untaxed" sum="Untaxed amount"/>
<field name="amount_tax"/>
<field name="amount_total" class="oe_form_subtotal_footer_separator"/>
</group>
<div class="oe_form_subtotal_footer" colspan="2">
<div>
<field name="amount_untaxed" sum="Untaxed amount"/>
</div>
<div>
<field name="amount_tax"/>
</div>
<div class="oe_form_subtotal_footer_separator">
<field name="amount_total"/>
</div>
</div>
<div class="oe_clear"/>
<separator colspan="4" string="Notes"/>
<field colspan="4" name="note" nolabel="1" placeholder="Our quotation is valid for 30 days..."/>
</group>
</page>
<page string="Other Information">
<group colspan="2" col="2" name="logistics">
+3 -5
View File
@@ -8,11 +8,9 @@
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="arch" type="xml">
<xpath expr="//div[@class='oe_form_subtotal_footer_separator']" position="after">
<div>
<field name="margin"/>
</div>
</xpath>
<field name="amount_total" position="after">
<field name="margin"/>
</field>
</field>
</record>