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.

266 lines
12 KiB

  1. from odoo import models, fields, api, _
  2. from odoo.exceptions import ValidationError, UserError
  3. from datetime import timedelta, datetime
  4. import logging
  5. class CooperativeStatus(models.Model):
  6. _inherit = 'cooperative.status'
  7. _period = 28
  8. ######################################################
  9. # #
  10. # Override of method to define status behavior #
  11. # #
  12. ######################################################
  13. future_alert_date = fields.Date(compute='_compute_future_alert_date')
  14. next_countdown_date = fields.Date(compute='_compute_next_countdown_date')
  15. @api.depends('today', 'irregular_start_date', 'sr', 'holiday_start_time',
  16. 'holiday_end_time', 'temporary_exempt_start_date',
  17. 'temporary_exempt_end_date')
  18. def _compute_future_alert_date(self):
  19. """Compute date before which the worker is up to date"""
  20. for rec in self:
  21. # Only for irregular worker
  22. if rec.working_mode != 'irregular' and not rec.irregular_start_date:
  23. rec.future_alert_date = False
  24. # Alert start time already set
  25. elif rec.alert_start_time:
  26. rec.future_alert_date = False
  27. # Holidays are not set properly
  28. elif bool(rec.holiday_start_time) != bool(rec.holiday_end_time):
  29. rec.future_alert_date = False
  30. # Exemption have not a start and end time
  31. elif (bool(rec.temporary_exempt_start_date)
  32. != bool(rec.temporary_exempt_end_date)):
  33. rec.future_alert_date = False
  34. else:
  35. date = rec.today
  36. counter = rec.sr
  37. # Simulate the countdown
  38. while counter > 0:
  39. date = add_days_delta(date, 1)
  40. date = self._next_countdown_date(rec.irregular_start_date,
  41. date)
  42. # Check holidays
  43. if (rec.holiday_start_time and rec.holiday_end_time
  44. and date >= rec.holiday_start_time
  45. and date <= rec.holiday_end_time):
  46. continue
  47. # Check temporary exemption
  48. elif (rec.temporary_exempt_start_date
  49. and rec.temporary_exempt_end_date
  50. and date >= rec.temporary_exempt_start_date
  51. and date <= rec.temporary_exempt_end_date):
  52. continue
  53. else:
  54. counter -= 1
  55. rec.future_alert_date = self._next_countdown_date(
  56. rec.irregular_start_date, date
  57. )
  58. @api.depends('today', 'irregular_start_date', 'holiday_start_time',
  59. 'holiday_end_time', 'temporary_exempt_start_date',
  60. 'temporary_exempt_end_date')
  61. def _compute_next_countdown_date(self):
  62. """
  63. Compute the following countdown date. This date is the date when
  64. the worker will see his counter changed du to the cron. This
  65. date is like the birthday date of the worker that occurred each
  66. PERIOD.
  67. """
  68. for rec in self:
  69. # Only for irregular worker
  70. if rec.working_mode != 'irregular' and not rec.irregular_start_date:
  71. rec.next_countdown_date = False
  72. # Holidays are not set properly
  73. elif bool(rec.holiday_start_time) != bool(rec.holiday_end_time):
  74. rec.next_countdown_date = False
  75. # Exemption have not a start and end time
  76. elif (bool(rec.temporary_exempt_start_date)
  77. != bool(rec.temporary_exempt_end_date)):
  78. rec.next_countdown_date = False
  79. else:
  80. date = rec.today
  81. next_countdown_date = False
  82. while not next_countdown_date:
  83. date = self._next_countdown_date(rec.irregular_start_date, date)
  84. # Check holidays
  85. if (rec.holiday_start_time and rec.holiday_end_time
  86. and date >= rec.holiday_start_time
  87. and date <= rec.holiday_end_time):
  88. date = add_days_delta(date, 1)
  89. continue
  90. # Check temporary exemption
  91. elif (rec.temporary_exempt_start_date
  92. and rec.temporary_exempt_end_date
  93. and date >= rec.temporary_exempt_start_date
  94. and date <= rec.temporary_exempt_end_date):
  95. date = add_days_delta(date, 1)
  96. continue
  97. else:
  98. next_countdown_date = date
  99. rec.next_countdown_date = next_countdown_date
  100. #####################################
  101. # Status Change implementation #
  102. #####################################
  103. def _set_regular_status(self, grace_delay, alert_delay):
  104. self.ensure_one()
  105. counter_unsubscribe = int(self.env['ir.config_parameter'].get_param('regular_counter_to_unsubscribe', -4))
  106. ok = self.sr >= 0 and self.sc >= 0
  107. grace_delay = grace_delay + self.time_extension
  108. if (self.sr + self.sc) <= counter_unsubscribe or self.unsubscribed:
  109. return 'unsubscribed'
  110. #Check if exempted. Exempt end date is not required.
  111. if self.temporary_exempt_start_date and self.today >= self.temporary_exempt_start_date:
  112. if not self.temporary_exempt_end_date or self.today <= self.temporary_exempt_end_date:
  113. return 'exempted'
  114. #Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and thus alert time is defined
  115. if not ok and self.alert_start_time and self.extension_start_time and self.today <= add_days_delta(self.extension_start_time, grace_delay):
  116. return 'extension'
  117. if not ok and self.alert_start_time and self.extension_start_time and self.today > add_days_delta(self.extension_start_time, grace_delay):
  118. return 'suspended'
  119. if not ok and self.alert_start_time and self.today > add_days_delta(self.alert_start_time, alert_delay):
  120. return 'suspended'
  121. if (self.sr < 0) or (not ok and self.alert_start_time):
  122. return 'alert'
  123. if (
  124. self.holiday_start_time
  125. and self.holiday_end_time
  126. and self.today >= self.holiday_start_time
  127. and self.today <= self.holiday_end_time
  128. ):
  129. return 'holiday'
  130. elif ok or (not self.alert_start_time and self.sr >= 0):
  131. return 'ok'
  132. def _set_irregular_status(self, grace_delay, alert_delay):
  133. counter_unsubscribe = int(self.env['ir.config_parameter'].get_param('irregular_counter_to_unsubscribe', -3))
  134. self.ensure_one()
  135. ok = self.sr >= 0
  136. grace_delay = grace_delay + self.time_extension
  137. if self.sr <= counter_unsubscribe or self.unsubscribed:
  138. return 'unsubscribed'
  139. #Check if exempted. Exempt end date is not required.
  140. elif self.temporary_exempt_start_date and self.today >= self.temporary_exempt_start_date:
  141. if not self.temporary_exempt_end_date or self.today <= self.temporary_exempt_end_date:
  142. return 'exempted'
  143. #Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and thus alert time is defined
  144. elif not ok and self.alert_start_time and self.extension_start_time and self.today <= add_days_delta(self.extension_start_time, grace_delay):
  145. return 'extension'
  146. elif not ok and self.alert_start_time and self.extension_start_time and self.today > add_days_delta(self.extension_start_time, grace_delay):
  147. return 'suspended'
  148. elif not ok and self.alert_start_time and self.today > add_days_delta(self.alert_start_time, alert_delay):
  149. return 'suspended'
  150. elif (self.sr < 0) or (not ok and self.alert_start_time):
  151. return 'alert'
  152. elif (
  153. self.holiday_start_time
  154. and self.holiday_end_time
  155. and self.today >= self.holiday_start_time
  156. and self.today <= self.holiday_end_time
  157. ):
  158. return 'holiday'
  159. elif ok or (not self.alert_start_time and self.sr >= 0):
  160. return 'ok'
  161. def _state_change(self, new_state):
  162. self.ensure_one()
  163. if new_state == 'alert':
  164. self.write({'alert_start_time': self.today, 'extension_start_time': False, 'time_extension': 0})
  165. if new_state == 'ok':
  166. data = {'extension_start_time': False, 'time_extension': 0}
  167. data['alert_start_time'] = False
  168. self.write(data)
  169. if new_state == 'unsubscribed' or new_state == 'resigning':
  170. # Remove worker from task_templates
  171. self.cooperator_id.sudo().write(
  172. {'subscribed_shift_ids': [(5, 0, 0)]})
  173. # Remove worker from supercoop in task_templates
  174. task_tpls = self.env['beesdoo.shift.template'].search(
  175. [('super_coop_id', 'in', self.cooperator_id.user_ids.ids)]
  176. )
  177. task_tpls.write({'super_coop_id': False})
  178. # Remove worker for future tasks (remove also supercoop)
  179. self.env['beesdoo.shift.shift'].sudo().unsubscribe_from_today(
  180. [self.cooperator_id.id], now=fields.Datetime.now()
  181. )
  182. def _change_counter(self, data):
  183. """
  184. Call when a shift state is changed
  185. use data generated by _get_counter_date_state_change
  186. """
  187. self.sc += data.get('sc', 0)
  188. self.sr += data.get('sr', 0)
  189. self.irregular_absence_counter += data.get('irregular_absence_counter', 0)
  190. self.irregular_absence_date = data.get('irregular_absence_date', False)
  191. ###############################################
  192. ###### Irregular Cron implementation ##########
  193. ###############################################
  194. def _get_irregular_worker_domain(self):
  195. return ['&',
  196. '&',
  197. '&',
  198. ('status', 'not in', ['unsubscribed', 'exempted']),
  199. ('working_mode', '=', 'irregular'),
  200. ('irregular_start_date', '!=', False),
  201. '|',
  202. '|', ('holiday_start_time', '=', False), ('holiday_end_time', '=', False),
  203. '|', ('holiday_start_time', '>', today), ('holiday_end_time', '<', today),
  204. ]
  205. def _change_irregular_counter(self):
  206. if self.sr > 0:
  207. self.sr -= 1
  208. elif self.alert_start_time:
  209. self.sr -= 1
  210. else:
  211. self.sr -= 2
  212. ##################################
  213. # Internal Implementation #
  214. ##################################
  215. def _next_countdown_date(self, irregular_start_date, today=False):
  216. """
  217. Return the next countdown date given irregular_start_date and
  218. today dates.
  219. This does not take holiday and other status into account.
  220. """
  221. today = today or fields.Date.today()
  222. delta = (today - irregular_start_date).days
  223. if not delta % PERIOD:
  224. return today
  225. return add_days_delta(today, PERIOD - (delta % PERIOD))
  226. class ResPartner(models.Model):
  227. _inherit = 'res.partner'
  228. """
  229. Override is_worker definition
  230. You need have subscribe to a A Share
  231. """
  232. is_worker = fields.Boolean(compute="_is_worker", search="_search_worker", readonly=True, related="")
  233. def _is_worker(self):
  234. for rec in self:
  235. rec.is_worker = rec.cooperator_type == 'share_a'
  236. def _search_worker(self, operator, value):
  237. if (operator == '=' and value) or (operator == '!=' and not value):
  238. return [('cooperator_type', '=', 'share_a')]
  239. else:
  240. return [('cooperator_type', '!=', 'share_a')]