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.

77 lines
3.1 KiB

  1. # Copyright 2017 Jairo Llopis <jairo.llopis@tecnativa.com>
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from __future__ import division
  4. from datetime import datetime
  5. from odoo import api, fields, models
  6. class ResPartner(models.Model):
  7. _inherit = "res.partner"
  8. phonecall_available = fields.Boolean(
  9. "Available to call",
  10. compute="_compute_phonecall_available",
  11. search="_search_phonecall_available",
  12. help="Is it now a good time to call this partner?",
  13. )
  14. phonecall_calendar_ids = fields.Many2many(
  15. comodel_name="resource.calendar",
  16. string="Phonecall schedule",
  17. help="Best schedule when the contact expects to be called.",
  18. )
  19. phonecall_calendar_attendance_ids = fields.One2many(
  20. comodel_name="resource.calendar.attendance",
  21. string="Aggregated phonecall schedule",
  22. compute="_compute_phonecall_calendar_ids",
  23. help="Aggregation of all available phonecall schedules.",
  24. )
  25. @api.depends("phonecall_calendar_ids", "phonecall_calendar_attendance_ids")
  26. def _compute_phonecall_available(self):
  27. """Know if a partner is available to call right now."""
  28. Attendance = self.env["resource.calendar.attendance"]
  29. for one in self:
  30. domain = [
  31. ("calendar_id", "in", one.phonecall_calendar_ids.ids)
  32. ] + one._phonecall_available_domain()
  33. found = Attendance.search(domain, limit=1)
  34. one.phonecall_available = bool(found)
  35. @api.depends("phonecall_calendar_ids")
  36. def _compute_phonecall_calendar_ids(self):
  37. """Fill attendance aggregation."""
  38. for one in self:
  39. one.phonecall_calendar_attendance_ids = one.mapped(
  40. "phonecall_calendar_ids.attendance_ids")
  41. def _search_phonecall_available(self, operator, value):
  42. """Search quickly if partner is available to call right now."""
  43. Attendance = self.env["resource.calendar.attendance"]
  44. available = Attendance.search(
  45. self._phonecall_available_domain(),
  46. )
  47. if operator == "!=" or "not" in operator:
  48. value = not value
  49. operator = "in" if value else "not in"
  50. return [("phonecall_calendar_ids.attendance_ids",
  51. operator, available.ids)]
  52. def _phonecall_available_domain(self):
  53. """Get a domain to know if we are available to call a partner."""
  54. now = self.env.context.get("now", datetime.now())
  55. try:
  56. now = fields.Datetime.from_string(now)
  57. except TypeError:
  58. # `now` is already a datetime object
  59. pass
  60. date = fields.Date.to_string(now)
  61. now_tz = fields.Datetime.context_timestamp(self, now)
  62. float_time = now_tz.hour + ((now_tz.minute / 60) + now_tz.second) / 60
  63. return [
  64. ("dayofweek", "=", str(now.weekday())),
  65. "|", ("date_from", "=", False), ("date_from", "<=", date),
  66. "|", ("date_to", "=", False), ("date_to", ">=", date),
  67. ("hour_from", "<=", float_time),
  68. ("hour_to", ">=", float_time),
  69. ]