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.

78 lines
3.1 KiB

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