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.

285 lines
10 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. from datetime import datetime
  2. from odoo import api, models, fields
  3. from odoo.addons.beesdoo_shift.models.cooperative_status import add_days_delta
  4. class TaskType(models.Model):
  5. _inherit = "beesdoo.shift.type"
  6. super_only = fields.Boolean('Referent Only')
  7. class TaskTemplate(models.Model):
  8. _inherit = 'beesdoo.shift.template'
  9. super_only = fields.Boolean(related="task_type_id.super_only")
  10. shift_presence_value = fields.Float(default=1.0)
  11. class WizardSubscribe(models.TransientModel):
  12. _inherit = 'beesdoo.shift.subscribe'
  13. def _get_mode(self):
  14. partner = self.env["res.partner"].browse(self._context.get("active_id"))
  15. return partner.working_mode or 'irregular'
  16. working_mode = fields.Selection(selection=[
  17. ("irregular", "worker"),
  18. ("exempt", "Exempted"),
  19. ], default=_get_mode)
  20. class Task(models.Model):
  21. _inherit = 'beesdoo.shift.shift'
  22. can_unsubscribe = fields.Boolean(compute="_compute_can_unsubscribe")
  23. super_only = fields.Boolean(related="task_type_id.super_only")
  24. def _get_selection_status(self):
  25. return [
  26. ("open","Confirmed"),
  27. ("done","Attended"),
  28. ("absent","Absent"),
  29. ("cancel","Cancelled")
  30. ]
  31. def _get_counter_date_state_change(self, new_state):
  32. """
  33. Return the cooperator_status of the cooperator that need to be
  34. change and data that need to be change. It does not perform the
  35. change directly. The cooperator_status will be changed by the
  36. _change_counter function.
  37. Check has been done to ensure that worker is legitimate.
  38. """
  39. data = {}
  40. status = self.worker_id.cooperative_status_ids[0]
  41. if new_state == "done":
  42. data['sr'] = self.task_template_id.shift_presence_value or 1.0
  43. return data, status
  44. def _compute_can_unsubscribe(self):
  45. now = datetime.now()
  46. ICP = self.env["ir.config_parameter"].sudo()
  47. max_hours = int(ICP.get_param("max_hours_to_unsubscribe", 2))
  48. for rec in self:
  49. if now > rec.start_time or rec.state != 'open':
  50. rec.can_unsubscribe = False
  51. else:
  52. delta = (rec.start_time - now)
  53. delta = delta.seconds / 3600.0 + delta.days * 24
  54. rec.can_unsubscribe = delta >= max_hours
  55. # def write(self, vals):
  56. # if 'worker_id' in vals:
  57. # template_unsubscribed = self.env.ref("macavrac_base.email_template_shift_unsubscribed")
  58. # template_subscribed = self.env.ref("macavrac_base.email_template_shift_subscribed")
  59. # new_worker_id = self.env['beesdoo.shift.shift'].browse(vals.get('worker_id'))
  60. # for record in self:
  61. # old_worker_id = record.worker_id
  62. # if old_worker_id:
  63. # template_unsubscribed.send_mail(record.id)
  64. # if new_worker_id and old_worker_id != new_worker_id:
  65. # res = super(Task, record).write(vals)
  66. # template_subscribed.send_mail(record.id)
  67. # return super(Task, self).write(vals)
  68. class CooperativeStatus(models.Model):
  69. _inherit = 'cooperative.status'
  70. def _get_status(self):
  71. return [
  72. ("ok", "Up to Date"),
  73. ("alert", "Alerte"),
  74. ("suspended", "Suspended"),
  75. ("exempted", "Exempted"),
  76. ("unsubscribed", "Unsubscribed"),
  77. ("resigning", "Resigning"),
  78. ]
  79. # TODO auto init for automatic migration
  80. sr = fields.Float()
  81. future_alert_date = fields.Date(compute="_compute_future_alert_date")
  82. next_countdown_date = fields.Date(compute="_compute_next_countdown_date")
  83. ########################################################
  84. # Method to override #
  85. # To define the behavior of the status #
  86. # #
  87. # By default: everyone is always up to date #
  88. ########################################################
  89. ##############################
  90. # Computed field section #
  91. ##############################
  92. def _next_countdown_date(self, irregular_start_date, today):
  93. """
  94. Return the next countdown date given irregular_start_date and
  95. today dates.
  96. This does not take holiday and other status into account.
  97. """
  98. delta = (today - irregular_start_date).days
  99. if not delta % self._period:
  100. return today
  101. return add_days_delta(today, self._period - (delta % self._period))
  102. @api.depends(
  103. "today",
  104. "sr",
  105. "temporary_exempt_start_date",
  106. "temporary_exempt_end_date",
  107. )
  108. def _compute_future_alert_date(self):
  109. """Compute date before which the worker is up to date"""
  110. for rec in self:
  111. #TODO fix infinite loop
  112. rec.future_alert_date = False
  113. continue
  114. # Only for irregular worker
  115. # Alert start time already set
  116. real_today = rec.today
  117. if rec.alert_start_time:
  118. rec.future_alert_date = False
  119. elif rec.working_mode != "irregular" or not rec.irregular_start_date:
  120. rec.future_alert_date = False
  121. else:
  122. date = rec.today
  123. counter = rec.sr
  124. next_countdown_date = False
  125. while counter >= 0:
  126. next_countdown_date = self._next_countdown_date(rec.irregular_start_date, date)
  127. rec.today = next_countdown_date
  128. if rec.status != 'exempted':
  129. counter -= 1
  130. rec.today = real_today
  131. date = add_days_delta(next_countdown_date, 1)
  132. rec.future_alert_date = next_countdown_date
  133. rec.today = real_today
  134. @api.depends(
  135. "today",
  136. "irregular_start_date",
  137. "holiday_start_time",
  138. "holiday_end_time",
  139. "temporary_exempt_start_date",
  140. "temporary_exempt_end_date",
  141. )
  142. def _compute_next_countdown_date(self):
  143. """
  144. Compute the following countdown date. This date is the date when
  145. the worker will see his counter changed du to the cron. This
  146. date is like the birthday date of the worker that occurred each
  147. PERIOD.
  148. """
  149. for rec in self:
  150. #TODO fix infinite loop
  151. rec.next_countdown_date = False
  152. continue
  153. real_today = rec.today
  154. # Only for irregular worker
  155. if rec.working_mode != "irregular" or not rec.irregular_start_date:
  156. rec.next_countdown_date = False
  157. else:
  158. next_countdown_date = rec.today
  159. while True:
  160. next_countdown_date = self._next_countdown_date(rec.irregular_start_date, next_countdown_date)
  161. rec.today = next_countdown_date
  162. if rec.status != 'exempted':
  163. rec.next_countdown_date = next_countdown_date
  164. rec.today = real_today
  165. break
  166. else:
  167. next_countdown_date = add_days_delta(next_countdown_date, 1)
  168. #####################################
  169. # Status Change implementation #
  170. #####################################
  171. def _get_regular_status(self):
  172. """
  173. Return the value of the status
  174. for the regular worker
  175. """
  176. ICP = self.env["ir.config_parameter"].sudo()
  177. suspended_count = int(ICP.get_param("suspended_count", -2))
  178. unsubscribed_count = int(ICP.get_param("unsubscribed_count", -4))
  179. if (self.temporary_exempt_start_date
  180. and self.temporary_exempt_end_date
  181. and self.today >= self.temporary_exempt_start_date
  182. and self.today <= self.temporary_exempt_end_date
  183. ):
  184. return 'exempted'
  185. if self.sr >= 0:
  186. return 'ok'
  187. if self.sr <= unsubscribed_count:
  188. return 'unsubscribed'
  189. if self.sr <= suspended_count:
  190. return 'suspended'
  191. if self.sr < 0:
  192. return 'alert'
  193. return 'ok'
  194. def _get_irregular_status(self):
  195. """
  196. Return the value of the status
  197. for the irregular worker
  198. """
  199. return self._get_regular_status()
  200. def _state_change(self, new_state):
  201. """
  202. Hook to watch change in the state
  203. """
  204. self.ensure_one()
  205. if new_state == "unsubscribed" or new_state == "resigning":
  206. # Remove worker from task_templates
  207. self.cooperator_id.sudo().write(
  208. {"subscribed_shift_ids": [(5, 0, 0)]}
  209. )
  210. # Remove worker from supercoop in task_templates
  211. task_tpls = self.env["beesdoo.shift.template"].search(
  212. [("super_coop_id", "in", self.cooperator_id.user_ids.ids)]
  213. )
  214. task_tpls.write({"super_coop_id": False})
  215. # Remove worker for future tasks (remove also supercoop)
  216. self.env["beesdoo.shift.shift"].sudo().unsubscribe_from_today(
  217. [self.cooperator_id.id], now=fields.Datetime.now()
  218. )
  219. if new_state == "alert":
  220. self.write({"alert_start_time": self.today})
  221. def _change_counter(self, data):
  222. """
  223. Call when a shift state is changed
  224. use data generated by _get_counter_date_state_change
  225. """
  226. self.sr += data.get("sr", 0)
  227. ###############################################
  228. ###### Irregular Cron implementation ##########
  229. ###############################################
  230. def _get_irregular_worker_domain(self, today):
  231. """
  232. return the domain the give the list
  233. of valid irregular worker that should
  234. get their counter changed by the cron
  235. """
  236. return [
  237. ("status", "not in", ["unsubscribed", "exempted", "resigning"]),
  238. ("irregular_start_date", "!=", False),
  239. ]
  240. def _change_irregular_counter(self):
  241. """
  242. Define how the counter will change
  243. for the irregular worker
  244. where today - start_date is a multiple of the period
  245. by default 28 days
  246. """
  247. self.sr -= 1