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.

182 lines
7.2 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Odoo, Open Source Management Solution
  5. #
  6. # Copyright (c) All rights reserved:
  7. # (c) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
  8. # (c) 2012 Domsense srl (<http://www.domsense.com>)
  9. # (c) 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es)
  10. # Alejandro Santana <alejandrosantana@anubia.es>
  11. # (c) 2015 Savoir-faire Linux <http://www.savoirfairelinux.com>)
  12. # Agathe Mollé <agathe.molle@savoirfairelinux.com>
  13. #
  14. # This program is free software: you can redistribute it and/or modify
  15. # it under the terms of the GNU Affero General Public License as
  16. # published by the Free Software Foundation, either version 3 of the
  17. # License, or (at your option) any later version.
  18. #
  19. # This program is distributed in the hope that it will be useful,
  20. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. # GNU Affero General Public License for more details.
  23. #
  24. # You should have received a copy of the GNU Affero General Public License
  25. # along with this program. If not, see http://www.gnu.org/licenses
  26. #
  27. ##############################################################################
  28. import logging
  29. from datetime import datetime
  30. from pytz import timezone, utc
  31. from mako.template import Template
  32. from openerp import _, api, exceptions, fields, models, tools
  33. from openerp.tools.safe_eval import safe_eval
  34. _logger = logging.getLogger(__name__)
  35. class SuperCalendarConfigurator(models.Model):
  36. _name = 'super.calendar.configurator'
  37. name = fields.Char(
  38. string='Name',
  39. required=True,
  40. )
  41. line_ids = fields.One2many(
  42. comodel_name='super.calendar.configurator.line',
  43. inverse_name='configurator_id',
  44. string='Lines',
  45. )
  46. def _clear_super_calendar_records(self):
  47. """
  48. Remove old super_calendar records
  49. """
  50. super_calendar_pool = self.env['super.calendar']
  51. super_calendar_list = super_calendar_pool.search([])
  52. super_calendar_list.unlink()
  53. @api.multi
  54. def generate_calendar_records(self):
  55. """
  56. At every CRON execution, every 'super calendar' data is deleted and
  57. regenerated again.
  58. """
  59. # Remove old records
  60. self._clear_super_calendar_records()
  61. # Rebuild all calendar records
  62. configurator_list = self.search([])
  63. for configurator in configurator_list:
  64. for line in configurator.line_ids:
  65. configurator._generate_record_from_line(line)
  66. _logger.info('Calendar generated')
  67. return True
  68. @api.multi
  69. def _generate_record_from_line(self, line):
  70. """
  71. Create super_calendar records from super_calendar_configurator_line
  72. objects.
  73. """
  74. super_calendar_pool = self.env['super.calendar']
  75. values = self._get_record_values_from_line(line)
  76. for record in values:
  77. super_calendar_pool.create(values[record])
  78. @api.multi
  79. def _get_record_values_from_line(self, line):
  80. """
  81. Get super_calendar fields values from super_calendar_configurator_line
  82. objects.
  83. Check if the User value is a res.users.
  84. """
  85. res = {}
  86. current_pool = self.env[line.name.model]
  87. domain = line.domain and safe_eval(line.domain) or []
  88. current_record_list = current_pool.search(domain)
  89. for cur_rec in current_record_list:
  90. f_user = line.user_field_id.name
  91. f_descr = line.description_field_id.name
  92. f_date_start = line.date_start_field_id.name
  93. f_date_stop = line.date_stop_field_id.name
  94. f_duration = line.duration_field_id.name
  95. # Check if f_user refer to a res.users
  96. if (f_user and cur_rec[f_user] and
  97. cur_rec[f_user]._model._name != 'res.users'):
  98. raise exceptions.ValidationError(
  99. _("The 'User' field of record %s (%s) "
  100. "does not refer to res.users")
  101. % (cur_rec[f_descr], line.name.model))
  102. if ((cur_rec[f_descr] or line.description_code) and
  103. cur_rec[f_date_start]):
  104. duration = False
  105. if line.date_start_field_id.ttype == 'date':
  106. date_format = tools.DEFAULT_SERVER_DATE_FORMAT
  107. else:
  108. date_format = tools.DEFAULT_SERVER_DATETIME_FORMAT
  109. date_start = datetime.strptime(
  110. cur_rec[f_date_start], date_format
  111. )
  112. if (not line.duration_field_id and
  113. line.date_stop_field_id and
  114. cur_rec[f_date_start] and
  115. cur_rec[f_date_stop]):
  116. if line.date_stop_field_id.ttype == 'date':
  117. date_format = tools.DEFAULT_SERVER_DATE_FORMAT
  118. else:
  119. date_format = tools.DEFAULT_SERVER_DATETIME_FORMAT
  120. date_stop = datetime.strptime(
  121. cur_rec[f_date_stop], date_format
  122. )
  123. date_diff = (date_stop - date_start)
  124. duration = date_diff.total_seconds() / 3600
  125. elif line.duration_field_id:
  126. duration = cur_rec[f_duration]
  127. if line.description_type != 'code':
  128. name = cur_rec[f_descr]
  129. else:
  130. parse_dict = {'o': cur_rec}
  131. mytemplate = Template(line.description_code)
  132. name = mytemplate.render(**parse_dict)
  133. # Convert date_start to UTC timezone if it is a date field
  134. # in order to be stored in UTC in the database
  135. if line.date_start_field_id.ttype == 'date':
  136. tz = timezone(self._context.get('tz') or
  137. self.env.user.tz or
  138. 'UTC')
  139. local_date_start = tz.localize(date_start)
  140. utc_date_start = local_date_start.astimezone(utc)
  141. date_start = utc_date_start
  142. date_start = datetime.strftime(
  143. date_start,
  144. tools.DEFAULT_SERVER_DATETIME_FORMAT
  145. )
  146. # Recurrent events have an string id like '14-20151110120000'
  147. # We need to split that to get the first part (id)
  148. if isinstance(cur_rec['id'], basestring):
  149. rec_id = cur_rec['id'].split('-')[0]
  150. else:
  151. rec_id = cur_rec['id']
  152. super_calendar_values = {
  153. 'name': name,
  154. 'date_start': date_start,
  155. 'duration': duration,
  156. 'user_id': (f_user and cur_rec[f_user].id),
  157. 'configurator_id': self.id,
  158. 'res_id': line.name.model + ',' + str(rec_id),
  159. 'model_id': line.name.id,
  160. }
  161. res[cur_rec] = super_calendar_values
  162. return res