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.

202 lines
7.8 KiB

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