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.

205 lines
7.9 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016 Odoo SA <https://www.odoo.com>
  3. # Copyright 2018 Eficent <http://www.eficent.com>
  4. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
  5. from datetime import date, datetime, timedelta
  6. from odoo import api, fields, models
  7. class MailActivity(models.Model):
  8. """ An actual activity to perform. Activities are linked to
  9. documents using res_id and res_model_id fields. Activities have a deadline
  10. that can be used in kanban view to display a status. Once done activities
  11. are unlinked and a message is posted. This message has a new
  12. activity_type_id field that indicates the activity linked to the message.
  13. """
  14. _name = 'mail.activity'
  15. _description = 'Activity'
  16. _order = 'date_deadline ASC'
  17. _rec_name = 'summary'
  18. @api.model
  19. def default_get(self, fields):
  20. res = super(MailActivity, self).default_get(fields)
  21. if not fields or 'res_model_id' in fields and res.get('res_model'):
  22. res['res_model_id'] = self.env['ir.model'].search([
  23. ('model', '=', res['res_model']),
  24. ]).id
  25. return res
  26. # owner
  27. res_id = fields.Integer('Related Document ID', index=True, required=True)
  28. res_model_id = fields.Many2one(
  29. 'ir.model', 'Related Document Model',
  30. index=True, ondelete='cascade', required=True)
  31. res_model = fields.Char(
  32. 'Related Document Model',
  33. index=True, related='res_model_id.model', store=True, readonly=True)
  34. res_name = fields.Char(
  35. 'Document Name', compute='_compute_res_name', store=True,
  36. help="Display name of the related document.", readonly=True)
  37. # activity
  38. activity_type_id = fields.Many2one(
  39. 'mail.activity.type', 'Activity',
  40. domain="['|', ('res_model_id', '=', False), "
  41. "('res_model_id', '=', res_model_id)]")
  42. activity_category = fields.Selection(related='activity_type_id.category')
  43. icon = fields.Char('Icon', related='activity_type_id.icon')
  44. summary = fields.Char('Summary')
  45. note = fields.Html('Note')
  46. feedback = fields.Html('Feedback')
  47. date_deadline = fields.Date(
  48. 'Due Date', index=True, required=True, default=fields.Date.today,
  49. )
  50. # description
  51. user_id = fields.Many2one(
  52. 'res.users', 'Assigned to',
  53. default=lambda self: self.env.user,
  54. index=True, required=True)
  55. state = fields.Selection([
  56. ('overdue', 'Overdue'),
  57. ('today', 'Today'),
  58. ('planned', 'Planned')], 'State',
  59. compute='_compute_state')
  60. recommended_activity_type_id = fields.Many2one(
  61. 'mail.activity.type', string="Recommended Activity Type",
  62. )
  63. previous_activity_type_id = fields.Many2one(
  64. 'mail.activity.type', string='Previous Activity Type',
  65. )
  66. has_recommended_activities = fields.Boolean(
  67. 'Next activities available',
  68. compute='_compute_has_recommended_activities',
  69. help='Technical field for UX purpose')
  70. @api.multi
  71. @api.onchange('previous_activity_type_id')
  72. def _compute_has_recommended_activities(self):
  73. for record in self:
  74. record.has_recommended_activities = bool(
  75. record.previous_activity_type_id.next_type_ids
  76. )
  77. @api.depends('res_model', 'res_id')
  78. def _compute_res_name(self):
  79. for activity in self:
  80. activity.res_name = self.env[activity.res_model].browse(
  81. activity.res_id
  82. ).name_get()[0][1]
  83. @api.depends('date_deadline')
  84. def _compute_state(self):
  85. today = date.today()
  86. for record in self.filtered(lambda activity: activity.date_deadline):
  87. date_deadline = fields.Date.from_string(record.date_deadline)
  88. diff = (date_deadline - today)
  89. if diff.days == 0:
  90. record.state = 'today'
  91. elif diff.days < 0:
  92. record.state = 'overdue'
  93. else:
  94. record.state = 'planned'
  95. @api.onchange('activity_type_id')
  96. def _onchange_activity_type_id(self):
  97. if self.activity_type_id:
  98. self.summary = self.activity_type_id.summary
  99. self.date_deadline = (
  100. datetime.now() + timedelta(days=self.activity_type_id.days)
  101. )
  102. @api.onchange('previous_activity_type_id')
  103. def _onchange_previous_activity_type_id(self):
  104. if self.previous_activity_type_id.next_type_ids:
  105. self.recommended_activity_type_id =\
  106. self.previous_activity_type_id.next_type_ids[0]
  107. @api.onchange('recommended_activity_type_id')
  108. def _onchange_recommended_activity_type_id(self):
  109. self.activity_type_id = self.recommended_activity_type_id
  110. @api.model
  111. def create(self, values):
  112. activity = super(MailActivity, self).create(values)
  113. self.env[activity.res_model].browse(activity.res_id).message_subscribe(
  114. partner_ids=[activity.user_id.partner_id.id]
  115. )
  116. if activity.date_deadline <= fields.Date.today():
  117. self.env['bus.bus'].sendone(
  118. (
  119. self._cr.dbname, 'res.partner',
  120. activity.user_id.partner_id.id
  121. ),
  122. {'type': 'activity_updated', 'activity_created': True})
  123. return activity
  124. @api.multi
  125. def write(self, values):
  126. if values.get('user_id'):
  127. pre_responsibles = self.mapped('user_id.partner_id')
  128. res = super(MailActivity, self).write(values)
  129. if values.get('user_id'):
  130. for activity in self:
  131. self.env[activity.res_model].browse(
  132. activity.res_id
  133. ).message_subscribe(
  134. partner_ids=[activity.user_id.partner_id.id]
  135. )
  136. if activity.date_deadline <= fields.Date.today():
  137. self.env['bus.bus'].sendone(
  138. (
  139. self._cr.dbname, 'res.partner',
  140. activity.user_id.partner_id.id
  141. ),
  142. {'type': 'activity_updated', 'activity_created': True})
  143. for activity in self:
  144. if activity.date_deadline <= fields.Date.today():
  145. for partner in pre_responsibles:
  146. self.env['bus.bus'].sendone(
  147. (self._cr.dbname, 'res.partner', partner.id),
  148. {
  149. 'type': 'activity_updated',
  150. 'activity_deleted': True
  151. }
  152. )
  153. return res
  154. @api.multi
  155. def unlink(self):
  156. for activity in self:
  157. if activity.date_deadline <= fields.Date.today():
  158. self.env['bus.bus'].sendone(
  159. (
  160. self._cr.dbname, 'res.partner',
  161. activity.user_id.partner_id.id
  162. ),
  163. {'type': 'activity_updated', 'activity_deleted': True})
  164. return super(MailActivity, self).unlink()
  165. @api.multi
  166. def action_done(self):
  167. """ Wrapper without feedback because web button add context as
  168. parameter, therefore setting context to feedback """
  169. return self.action_feedback()
  170. @api.multi
  171. def action_feedback(self, feedback=False):
  172. message = self.env['mail.message']
  173. if feedback:
  174. self.write(dict(feedback=feedback))
  175. for activity in self:
  176. record = self.env[activity.res_model].browse(activity.res_id)
  177. record.message_post_with_view(
  178. 'mail.message_activity_done',
  179. values={'activity': activity},
  180. subtype_id=self.env.ref('mail.mt_activities').id,
  181. mail_activity_type_id=activity.activity_type_id.id,
  182. )
  183. message |= record.message_ids[0]
  184. self.unlink()
  185. return {'type': 'ir.actions.act_window_close'}
  186. @api.multi
  187. def action_close_dialog(self):
  188. return {'type': 'ir.actions.act_window_close'}