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.

351 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_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 not r.parent_id or not (r.parent_id.model == r.model and
  143. r.parent_id.res_id == r.res_id):
  144. #link with the first message of record
  145. parent = self.env['mail.message'].search([('model','=',r.model), ('res_id','=',r.res_id)], order='id', limit=1)
  146. r.parent_id = parent.id or None
  147. r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back)
  148. if not ( r.model and r.res_id ):
  149. obj = self.pool.get('ir.model.data').get_object_reference(self._cr, SUPERUSER_ID, 'mail', 'mail_archivesfeeds')[1]
  150. return {
  151. 'type' : 'ir.actions.client',
  152. 'name' : 'Archive',
  153. 'tag' : 'reload',
  154. 'params' : {'menu_id': obj},
  155. }
  156. return {
  157. 'name': _('Record'),
  158. 'view_type': 'form',
  159. 'view_mode': 'form',
  160. 'res_model': r.model,
  161. 'res_id': r.res_id,
  162. 'views': [(False, 'form')],
  163. 'type': 'ir.actions.act_window',
  164. }
  165. @api.one
  166. def delete(self):
  167. self.message_id.unlink()
  168. return {}
  169. @api.model
  170. def create_partner(self, message_id, relation, partner_id, message_name_from, message_email_from):
  171. model = self.env[relation]
  172. message = self.env['mail.message'].browse(message_id)
  173. if not partner_id and message_name_from:
  174. partner_id = self.env['res.partner'].with_context({'update_message_author': True}).create({
  175. 'name': message_name_from,
  176. 'email': message_email_from
  177. }).id
  178. context = {'partner_id': partner_id}
  179. if model._rec_name:
  180. context.update({'default_%s' % model._rec_name: message.subject})
  181. fields = model.fields_get()
  182. contact_field = False
  183. for n, f in fields.iteritems():
  184. if f['type'] == 'many2one' and f['relation'] == 'res.partner':
  185. contact_field = n
  186. break
  187. if contact_field:
  188. context.update({'default_%s' % contact_field: partner_id})
  189. return context
  190. @api.one
  191. def read_close(self):
  192. self.message_id.set_message_read(True)
  193. self.message_id.child_ids.set_message_read(True)
  194. return {'type': 'ir.actions.act_window_close'}
  195. class mail_message(models.Model):
  196. _inherit = 'mail.message'
  197. is_moved = fields.Boolean('Is moved')
  198. moved_from_res_id = fields.Integer('Related Document ID (Original)')
  199. moved_from_model = fields.Char('Related Document Model (Original)')
  200. moved_from_parent_id = fields.Many2one('mail.message', 'Parent Message (Original)', ondelete='set null')
  201. moved_by_message_id = fields.Many2one('mail.message', 'Moved by message', ondelete='set null', help='Top message, that initate moving this message')
  202. moved_by_user_id = fields.Many2one('res.users', 'Moved by user', ondelete='set null')
  203. all_child_ids = fields.One2many('mail.message', string='All childs', compute='_get_all_childs', help='all childs, including subchilds')
  204. @api.one
  205. def _get_all_childs(self, include_myself=True):
  206. ids = []
  207. if include_myself:
  208. ids.append(self.id)
  209. while True:
  210. new_ids = self.search([('parent_id', 'in', ids), ('id', 'not in', ids)]).ids
  211. if new_ids:
  212. ids = ids + new_ids
  213. continue
  214. break
  215. moved_childs = self.search([('moved_by_message_id', '=', self.id)]).ids
  216. self.all_child_ids = ids + moved_childs
  217. @api.one
  218. def move(self, parent_id, res_id, model, move_back):
  219. vals = {}
  220. if move_back:
  221. # clear variables if we move everything back
  222. vals['is_moved'] = False
  223. vals['moved_by_user_id'] = None
  224. vals['moved_by_message_id'] = None
  225. vals['moved_from_res_id'] = None
  226. vals['moved_from_model'] = None
  227. vals['moved_from_parent_id'] = None
  228. else:
  229. vals['parent_id'] = parent_id
  230. vals['res_id'] = res_id
  231. vals['model'] = model
  232. vals['is_moved'] = True
  233. vals['moved_by_user_id'] = self.env.user.id
  234. vals['moved_by_message_id'] = self.id
  235. for r in self.all_child_ids:
  236. r_vals = vals.copy()
  237. if not r.is_moved:
  238. # moved_from_* variables contain not last, but original
  239. # reference
  240. r_vals['moved_from_parent_id'] = r.parent_id.id
  241. r_vals['moved_from_res_id'] = r.res_id
  242. r_vals['moved_from_model'] = r.model
  243. elif move_back:
  244. r_vals['parent_id'] = r.moved_from_parent_id.id
  245. r_vals['res_id'] = r.moved_from_res_id
  246. r_vals['model'] = r.moved_from_model
  247. print 'update message', r, r_vals
  248. r.sudo().write(r_vals)
  249. def name_get(self, cr, uid, ids, context=None):
  250. if not (context or {}).get('extended_name'):
  251. return super(mail_message, self).name_get(cr, uid, ids, context=context)
  252. if isinstance(ids, (list, tuple)) and not len(ids):
  253. return []
  254. if isinstance(ids, (long, int)):
  255. ids = [ids]
  256. reads = self.read(cr, uid, ids, ['record_name','model', 'res_id'], context=context)
  257. res = []
  258. for record in reads:
  259. name = record['record_name'] or ''
  260. extended_name = ' [%s] ID %s' % (record.get('model', 'UNDEF'), record.get('res_id', 'UNDEF'))
  261. res.append((record['id'], name + extended_name))
  262. return res
  263. def _message_read_dict(self, cr, uid, message, parent_id=False, context=None):
  264. res = super(mail_message, self)._message_read_dict(cr, uid, message, parent_id, context)
  265. res['is_moved'] = message.is_moved
  266. return res
  267. class mail_move_message_configuration(models.TransientModel):
  268. _name = 'mail_move_message.config.settings'
  269. _inherit = 'res.config.settings'
  270. model_ids = fields.Many2many(comodel_name='ir.model', string='Models')
  271. @api.model
  272. def get_default_model_ids(self, fields):
  273. config_parameters = self.env['ir.config_parameter']
  274. model_obj = self.env['ir.model']
  275. model_names = config_parameters.get_param('mail_relocation_models')
  276. if not model_names:
  277. return {}
  278. model_names = model_names.split(',')
  279. model_ids = model_obj.search([('model', 'in', model_names)])
  280. return {'model_ids': [m.id for m in model_ids]}
  281. @api.multi
  282. def set_model_ids(self):
  283. config_parameters = self.env['ir.config_parameter']
  284. model_names = ''
  285. for record in self:
  286. model_names = ','.join([m.model for m in record.model_ids])
  287. config_parameters.set_param('mail_relocation_models', model_names)
  288. class res_partner(models.Model):
  289. _inherit = 'res.partner'
  290. @api.model
  291. def create(self, vals):
  292. res = super(res_partner, self).create(vals)
  293. if 'update_message_author' in self.env.context and 'email' in vals:
  294. mail_message_obj = self.env['mail.message']
  295. # Escape special SQL characters in email_address to avoid invalid matches
  296. email_address = (vals['email'].replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_'))
  297. email_brackets = "<%s>" % email_address
  298. messages = mail_message_obj.search([
  299. '|',
  300. ('email_from', '=ilike', email_address),
  301. ('email_from', 'ilike', email_brackets),
  302. ('author_id', '=', False)
  303. ])
  304. if messages:
  305. messages.sudo().write({'author_id': res.id})
  306. return res