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.

76 lines
3.0 KiB

  1. # Copyright 2017 Tecnativa - Jairo Llopis
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from datetime import datetime
  4. from odoo import api, fields, models
  5. class ResPartner(models.Model):
  6. """Added phonecall details in the partner."""
  7. _inherit = "res.partner"
  8. phonecall_available = fields.Boolean(
  9. string="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. )
  42. def _search_phonecall_available(self, operator, value):
  43. """Search quickly if partner is available to call right now."""
  44. Attendance = self.env["resource.calendar.attendance"]
  45. available = Attendance.search(self._phonecall_available_domain())
  46. if operator == "!=" or "not" in operator:
  47. value = not value
  48. operator = "in" if value else "not in"
  49. return [("phonecall_calendar_ids.attendance_ids", operator, available.ids)]
  50. def _phonecall_available_domain(self):
  51. """Get a domain to know if we are available to call a partner."""
  52. now = fields.Datetime.from_string(self.env.context.get("now", datetime.now()))
  53. date = fields.Date.to_string(now)
  54. now_tz = fields.Datetime.context_timestamp(self, now)
  55. float_time = now_tz.hour + ((now_tz.minute / 60) + now_tz.second) / 60
  56. return [
  57. ("dayofweek", "=", str(now.weekday())),
  58. "|",
  59. ("date_from", "=", False),
  60. ("date_from", "<=", date),
  61. "|",
  62. ("date_to", "=", False),
  63. ("date_to", ">=", date),
  64. ("hour_from", "<=", float_time),
  65. ("hour_to", ">=", float_time),
  66. ]