You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
15 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. from lxml import etree
  2. from openerp import api, models, fields, SUPERUSER_ID
  3. from openerp.tools import email_split
  4. from openerp.tools.translate import _
  5. class wizard(models.TransientModel):
  6. _name = 'mail_move_message.wizard'
  7. def _model_selection(self):
  8. selection = []
  9. config_parameters = self.env['ir.config_parameter']
  10. model_names = config_parameters.get_param('mail_relocation_models')
  11. model_names = model_names.split(',') if model_names else []
  12. if 'default_message_id' in self.env.context:
  13. message = self.env['mail.message'].browse(self.env.context['default_message_id'])
  14. if message.model and message.model not in model_names:
  15. model_names.append(message.model)
  16. if message.moved_from_model and message.moved_from_model not in model_names:
  17. model_names.append(message.moved_from_model)
  18. if model_names:
  19. selection = [(m.model, m.display_name) for m in self.env['ir.model'].search([('model', 'in', model_names)])]
  20. return selection
  21. @api.model
  22. def default_get(self, fields_list):
  23. res = super(wizard, self).default_get(fields_list)
  24. model_fields = self.fields_get()
  25. if model_fields['model']['selection']:
  26. res['model'] = model_fields['model']['selection'] and model_fields['model']['selection'][0][0]
  27. if 'message_id' in res:
  28. message = self.env['mail.message'].browse(res['message_id'])
  29. email_from = message.email_from
  30. parts = email_split(email_from.replace(' ',','))
  31. if parts:
  32. email = parts[0]
  33. name = email_from[:email_from.index(email)].replace('"', '').replace('<', '').strip() or email_from
  34. else:
  35. name, email = email_from
  36. res['message_name_from'] = name
  37. res['message_email_from'] = email
  38. res['partner_id'] = message.author_id.id
  39. if message.author_id and self.env.uid not in [u.id for u in message.author_id.user_ids]:
  40. res['filter_by_partner'] = True
  41. if message.author_id and res.get('model'):
  42. res_id = self.env[res['model']].search([], order='id desc', limit=1)
  43. res['res_id'] = res_id and res_id[0].id
  44. res['uid'] = self.env.uid
  45. return res
  46. message_id = fields.Many2one('mail.message', string='Message')
  47. message_body = fields.Html(related='message_id.body', string='Message to move', readonly=True)
  48. message_from = fields.Char(related='message_id.email_from', string='From', readonly=True)
  49. message_subject = fields.Char(related='message_id.subject', string='Subject', readonly=True)
  50. message_moved_by_message_id = fields.Many2one('mail.message', related='message_id.moved_by_message_id', string='Moved with', readonly=True)
  51. message_moved_by_user_id = fields.Many2one('res.users', related='message_id.moved_by_user_id', string='Moved by', readonly=True)
  52. message_is_moved = fields.Boolean(string='Is Moved', related='message_id.is_moved', readonly=True)
  53. parent_id = fields.Many2one('mail.message', string='Search by name', )
  54. model = fields.Selection(_model_selection, string='Model')
  55. res_id = fields.Integer(string='Record')
  56. can_move = fields.Boolean('Can move', compute='get_can_move')
  57. move_back = fields.Boolean('MOVE TO ORIGIN', help='Move message and submessages to original place')
  58. partner_id = fields.Many2one('res.partner', string='Author')
  59. filter_by_partner = fields.Boolean('Filter Records by partner')
  60. message_email_from = fields.Char()
  61. message_name_from = fields.Char()
  62. # FIXME message_to_read should be True even if current message or any his childs are unread
  63. message_to_read = fields.Boolean(related='message_id.to_read')
  64. uid = fields.Integer()
  65. @api.depends('message_id')
  66. @api.one
  67. def get_can_move(self):
  68. # message was not moved before OR message is a top message of previous move
  69. self.can_move = not self.message_id.moved_by_message_id or self.message_id.moved_by_message_id.id == self.message_id.id
  70. @api.onchange('move_back')
  71. def on_change_move_back(self):
  72. if not self.move_back:
  73. return
  74. self.parent_id = self.message_id.moved_from_parent_id
  75. model = self.message_id.moved_from_model
  76. if self.message_id.is_moved:
  77. self.model = model
  78. self.res_id = self.message_id.moved_from_res_id
  79. @api.onchange('parent_id', 'res_id', 'model')
  80. def update_move_back(self):
  81. model = self.message_id.moved_from_model
  82. self.move_back = self.parent_id == self.message_id.moved_from_parent_id \
  83. and self.res_id == self.message_id.moved_from_res_id \
  84. and (self.model == model or (not self.model and not model))
  85. @api.onchange('parent_id')
  86. def on_change_parent_id(self):
  87. if self.parent_id and self.parent_id.model:
  88. self.model = self.parent_id.model
  89. self.res_id = self.parent_id.res_id
  90. else:
  91. self.model = None
  92. self.res_id = None
  93. @api.onchange('model', 'filter_by_partner', 'partner_id')
  94. def on_change_partner(self):
  95. domain = {'res_id': []}
  96. if self.model and self.filter_by_partner and self.partner_id:
  97. fields = self.env[self.model].fields_get(False)
  98. contact_field = False
  99. for n, f in fields.iteritems():
  100. if f['type'] == 'many2one' and f['relation'] == 'res.partner':
  101. contact_field = n
  102. break
  103. if contact_field:
  104. domain['res_id'] = [(contact_field, '=', self.partner_id.id)]
  105. if self.model:
  106. res_id = self.env[self.model].search(domain['res_id'], order='id desc', limit=1)
  107. self.res_id = res_id and res_id[0].id
  108. else:
  109. self.res_id = None
  110. return {'domain': domain}
  111. @api.one
  112. def check_access(self):
  113. cr = self._cr
  114. uid = self.env.user.id
  115. operation = 'write'
  116. context = self._context
  117. if not ( self.model and self.res_id ):
  118. return True
  119. model_obj = self.pool[self.model]
  120. mids = model_obj.exists(cr, uid, [self.res_id])
  121. if hasattr(model_obj, 'check_mail_message_access'):
  122. model_obj.check_mail_message_access(cr, uid, mids, operation, context=context)
  123. else:
  124. self.pool['mail.thread'].check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context)
  125. @api.multi
  126. def open_moved_by_message_id(self):
  127. message_id = None
  128. for r in self:
  129. message_id = r.message_moved_by_message_id.id
  130. return {
  131. 'type': 'ir.actions.act_window',
  132. 'res_model': 'mail_move_message.wizard',
  133. 'view_mode': 'form',
  134. 'view_type': 'form',
  135. 'views': [[False, 'form']],
  136. 'target': 'new',
  137. 'context': {'default_message_id': message_id},
  138. }
  139. @api.multi
  140. def move(self):
  141. for r in self:
  142. r.check_access()
  143. if not r.parent_id or not (r.parent_id.model == r.model and
  144. r.parent_id.res_id == r.res_id):
  145. #link with the first message of record
  146. parent = self.env['mail.message'].search([('model','=',r.model), ('res_id','=',r.res_id)], order='id', limit=1)
  147. r.parent_id = parent.id or None
  148. r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back)
  149. if not ( r.model and r.res_id ):
  150. obj = self.pool.get('ir.model.data').get_object_reference(self._cr, SUPERUSER_ID, 'mail', 'mail_archivesfeeds')[1]
  151. return {
  152. 'type' : 'ir.actions.client',
  153. 'name' : 'Archive',
  154. 'tag' : 'reload',
  155. 'params' : {'menu_id': obj},
  156. }
  157. return {
  158. 'name': _('Record'),
  159. 'view_type': 'form',
  160. 'view_mode': 'form',
  161. 'res_model': r.model,
  162. 'res_id': r.res_id,
  163. 'views': [(False, 'form')],
  164. 'type': 'ir.actions.act_window',
  165. }
  166. @api.one
  167. def delete(self):
  168. self.message_id.unlink()
  169. return {}
  170. @api.model
  171. def create_partner(self, message_id, relation, partner_id, message_name_from, message_email_from):
  172. model = self.env[relation]
  173. message = self.env['mail.message'].browse(message_id)
  174. if not partner_id and message_name_from:
  175. partner_id = self.env['res.partner'].with_context({'update_message_author': True}).create({
  176. 'name': message_name_from,
  177. 'email': message_email_from
  178. }).id
  179. context = {'partner_id': partner_id}
  180. if model._rec_name:
  181. context.update({'default_%s' % model._rec_name: message.subject})
  182. fields = model.fields_get()
  183. contact_field = False
  184. for n, f in fields.iteritems():
  185. if f['type'] == 'many2one' and f['relation'] == 'res.partner':
  186. contact_field = n
  187. break
  188. if contact_field:
  189. context.update({'default_%s' % contact_field: partner_id})
  190. return context
  191. @api.one
  192. def read_close(self):
  193. self.message_id.set_message_read(True)
  194. self.message_id.child_ids.set_message_read(True)
  195. return {'type': 'ir.actions.act_window_close'}
  196. class mail_message(models.Model):
  197. _inherit = 'mail.message'
  198. is_moved = fields.Boolean('Is moved')
  199. moved_from_res_id = fields.Integer('Related Document ID (Original)')
  200. moved_from_model = fields.Char('Related Document Model (Original)')
  201. moved_from_parent_id = fields.Many2one('mail.message', 'Parent Message (Original)', ondelete='set null')
  202. moved_by_message_id = fields.Many2one('mail.message', 'Moved by message', ondelete='set null', help='Top message, that initate moving this message')
  203. moved_by_user_id = fields.Many2one('res.users', 'Moved by user', ondelete='set null')
  204. all_child_ids = fields.One2many('mail.message', string='All childs', compute='_get_all_childs', help='all childs, including subchilds')
  205. @api.one
  206. def _get_all_childs(self, include_myself=True):
  207. ids = []
  208. if include_myself:
  209. ids.append(self.id)
  210. while True:
  211. new_ids = self.search([('parent_id', 'in', ids), ('id', 'not in', ids)]).ids
  212. if new_ids:
  213. ids = ids + new_ids
  214. continue
  215. break
  216. moved_childs = self.search([('moved_by_message_id', '=', self.id)]).ids
  217. self.all_child_ids = ids + moved_childs
  218. @api.one
  219. def move(self, parent_id, res_id, model, move_back):
  220. vals = {}
  221. if move_back:
  222. # clear variables if we move everything back
  223. vals['is_moved'] = False
  224. vals['moved_by_user_id'] = None
  225. vals['moved_by_message_id'] = None
  226. vals['moved_from_res_id'] = None
  227. vals['moved_from_model'] = None
  228. vals['moved_from_parent_id'] = None
  229. else:
  230. vals['parent_id'] = parent_id
  231. vals['res_id'] = res_id
  232. vals['model'] = model
  233. vals['is_moved'] = True
  234. vals['moved_by_user_id'] = self.env.user.id
  235. vals['moved_by_message_id'] = self.id
  236. for r in self.all_child_ids:
  237. r_vals = vals.copy()
  238. if not r.is_moved:
  239. # moved_from_* variables contain not last, but original
  240. # reference
  241. r_vals['moved_from_parent_id'] = r.parent_id.id
  242. r_vals['moved_from_res_id'] = r.res_id
  243. r_vals['moved_from_model'] = r.model
  244. elif move_back:
  245. r_vals['parent_id'] = r.moved_from_parent_id.id
  246. r_vals['res_id'] = r.moved_from_res_id
  247. r_vals['model'] = r.moved_from_model
  248. print 'update message', r, r_vals
  249. r.sudo().write(r_vals)
  250. def name_get(self, cr, uid, ids, context=None):
  251. if not (context or {}).get('extended_name'):
  252. return super(mail_message, self).name_get(cr, uid, ids, context=context)
  253. if isinstance(ids, (list, tuple)) and not len(ids):
  254. return []
  255. if isinstance(ids, (long, int)):
  256. ids = [ids]
  257. reads = self.read(cr, uid, ids, ['record_name','model', 'res_id'], context=context)
  258. res = []
  259. for record in reads:
  260. name = record['record_name'] or ''
  261. extended_name = ' [%s] ID %s' % (record.get('model', 'UNDEF'), record.get('res_id', 'UNDEF'))
  262. res.append((record['id'], name + extended_name))
  263. return res
  264. def _message_read_dict(self, cr, uid, message, parent_id=False, context=None):
  265. res = super(mail_message, self)._message_read_dict(cr, uid, message, parent_id, context)
  266. res['is_moved'] = message.is_moved
  267. return res
  268. class mail_move_message_configuration(models.TransientModel):
  269. _name = 'mail_move_message.config.settings'
  270. _inherit = 'res.config.settings'
  271. model_ids = fields.Many2many(comodel_name='ir.model', string='Models')
  272. @api.model
  273. def get_default_model_ids(self, fields):
  274. config_parameters = self.env['ir.config_parameter']
  275. model_obj = self.env['ir.model']
  276. model_names = config_parameters.get_param('mail_relocation_models')
  277. if not model_names:
  278. return {}
  279. model_names = model_names.split(',')
  280. model_ids = model_obj.search([('model', 'in', model_names)])
  281. return {'model_ids': [m.id for m in model_ids]}
  282. @api.multi
  283. def set_model_ids(self):
  284. config_parameters = self.env['ir.config_parameter']
  285. model_names = ''
  286. for record in self:
  287. model_names = ','.join([m.model for m in record.model_ids])
  288. config_parameters.set_param('mail_relocation_models', model_names)
  289. class res_partner(models.Model):
  290. _inherit = 'res.partner'
  291. @api.model
  292. def create(self, vals):
  293. res = super(res_partner, self).create(vals)
  294. if 'update_message_author' in self.env.context and 'email' in vals:
  295. mail_message_obj = self.env['mail.message']
  296. # Escape special SQL characters in email_address to avoid invalid matches
  297. email_address = (vals['email'].replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_'))
  298. email_brackets = "<%s>" % email_address
  299. messages = mail_message_obj.search([
  300. '|',
  301. ('email_from', '=ilike', email_address),
  302. ('email_from', 'ilike', email_brackets),
  303. ('author_id', '=', False)
  304. ])
  305. if messages:
  306. messages.sudo().write({'author_id': res.id})
  307. return res