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.

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