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.

373 lines
14 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
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
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
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
4 years ago
4 years ago
4 years ago
  1. from odoo import api, fields, models
  2. from odoo.addons.beesdoo_shift.models.cooperative_status import add_days_delta
  3. class CooperativeStatus(models.Model):
  4. _inherit = "cooperative.status"
  5. _period = 28
  6. ######################################################
  7. # #
  8. # Override of method to define status behavior #
  9. # #
  10. ######################################################
  11. future_alert_date = fields.Date(compute="_compute_future_alert_date")
  12. next_countdown_date = fields.Date(compute="_compute_next_countdown_date")
  13. @api.depends(
  14. "today",
  15. "irregular_start_date",
  16. "sr",
  17. "holiday_start_time",
  18. "holiday_end_time",
  19. "temporary_exempt_start_date",
  20. "temporary_exempt_end_date",
  21. )
  22. def _compute_future_alert_date(self):
  23. """Compute date before which the worker is up to date"""
  24. for rec in self:
  25. # Only for irregular worker
  26. if (
  27. rec.working_mode != "irregular"
  28. and not rec.irregular_start_date
  29. ):
  30. rec.future_alert_date = False
  31. # Alert start time already set
  32. elif rec.alert_start_time:
  33. rec.future_alert_date = False
  34. # Holidays are not set properly
  35. elif bool(rec.holiday_start_time) != bool(rec.holiday_end_time):
  36. rec.future_alert_date = False
  37. # Exemption have not a start and end time
  38. elif bool(rec.temporary_exempt_start_date) != bool(
  39. rec.temporary_exempt_end_date
  40. ):
  41. rec.future_alert_date = False
  42. else:
  43. date = rec.today
  44. counter = rec.sr
  45. # Simulate the countdown
  46. while counter > 0:
  47. date = self._next_countdown_date(
  48. rec.irregular_start_date, date
  49. )
  50. # Check holidays
  51. if (
  52. rec.holiday_start_time
  53. and rec.holiday_end_time
  54. and date >= rec.holiday_start_time
  55. and date <= rec.holiday_end_time
  56. ):
  57. date = add_days_delta(date, 1)
  58. continue
  59. # Check temporary exemption
  60. if (
  61. rec.temporary_exempt_start_date
  62. and rec.temporary_exempt_end_date
  63. and date >= rec.temporary_exempt_start_date
  64. and date <= rec.temporary_exempt_end_date
  65. ):
  66. date = add_days_delta(date, 1)
  67. continue
  68. # Otherwise
  69. date = add_days_delta(date, 1)
  70. counter -= 1
  71. rec.future_alert_date = self._next_countdown_date(
  72. rec.irregular_start_date, date
  73. )
  74. @api.depends(
  75. "today",
  76. "irregular_start_date",
  77. "holiday_start_time",
  78. "holiday_end_time",
  79. "temporary_exempt_start_date",
  80. "temporary_exempt_end_date",
  81. )
  82. def _compute_next_countdown_date(self):
  83. """
  84. Compute the following countdown date. This date is the date when
  85. the worker will see his counter changed du to the cron. This
  86. date is like the birthday date of the worker that occurred each
  87. PERIOD.
  88. """
  89. for rec in self:
  90. # Only for irregular worker
  91. if (
  92. rec.working_mode != "irregular"
  93. and not rec.irregular_start_date
  94. ):
  95. rec.next_countdown_date = False
  96. # Holidays are not set properly
  97. elif bool(rec.holiday_start_time) != bool(rec.holiday_end_time):
  98. rec.next_countdown_date = False
  99. # Exemption have not a start and end time
  100. elif bool(rec.temporary_exempt_start_date) != bool(
  101. rec.temporary_exempt_end_date
  102. ):
  103. rec.next_countdown_date = False
  104. else:
  105. date = rec.today
  106. next_countdown_date = False
  107. while not next_countdown_date:
  108. date = self._next_countdown_date(
  109. rec.irregular_start_date, date
  110. )
  111. # Check holidays
  112. if (
  113. rec.holiday_start_time
  114. and rec.holiday_end_time
  115. and date >= rec.holiday_start_time
  116. and date <= rec.holiday_end_time
  117. ):
  118. date = add_days_delta(date, 1)
  119. continue
  120. # Check temporary exemption
  121. if (
  122. rec.temporary_exempt_start_date
  123. and rec.temporary_exempt_end_date
  124. and date >= rec.temporary_exempt_start_date
  125. and date <= rec.temporary_exempt_end_date
  126. ):
  127. date = add_days_delta(date, 1)
  128. continue
  129. # Otherwise
  130. next_countdown_date = date
  131. rec.next_countdown_date = next_countdown_date
  132. #####################################
  133. # Status Change implementation #
  134. #####################################
  135. def _get_regular_status(self):
  136. self.ensure_one()
  137. counter_unsubscribe = int(
  138. self.env["ir.config_parameter"]
  139. .sudo()
  140. .get_param("regular_counter_to_unsubscribe", -4)
  141. )
  142. alert_delay = int(
  143. self.env["ir.config_parameter"].sudo().get_param("alert_delay", 28)
  144. )
  145. grace_delay = int(
  146. self.env["ir.config_parameter"]
  147. .sudo()
  148. .get_param("default_grace_delay", 10)
  149. )
  150. ok = self.sr >= 0 and self.sc >= 0
  151. grace_delay = grace_delay + self.time_extension
  152. if (self.sr + self.sc) <= counter_unsubscribe or self.unsubscribed:
  153. return "unsubscribed"
  154. # Check if exempted. Exempt end date is not required.
  155. if (
  156. # Start and end are defined
  157. self.temporary_exempt_start_date
  158. and self.temporary_exempt_end_date
  159. and self.today >= self.temporary_exempt_start_date
  160. and self.today <= self.temporary_exempt_end_date
  161. ) or (
  162. # Only start is defined
  163. self.temporary_exempt_start_date
  164. and not self.temporary_exempt_end_date
  165. and self.today >= self.temporary_exempt_start_date
  166. ):
  167. return "exempted"
  168. # Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and
  169. # thus alert time is defined
  170. if (
  171. not ok
  172. and self.alert_start_time
  173. and self.extension_start_time
  174. and self.today
  175. <= add_days_delta(self.extension_start_time, grace_delay)
  176. ):
  177. return "extension"
  178. if (
  179. not ok
  180. and self.alert_start_time
  181. and self.extension_start_time
  182. and self.today
  183. > add_days_delta(self.extension_start_time, grace_delay)
  184. ):
  185. return "suspended"
  186. if (
  187. not ok
  188. and self.alert_start_time
  189. and self.today > add_days_delta(self.alert_start_time, alert_delay)
  190. ):
  191. return "suspended"
  192. if (self.sr < 0) or (not ok and self.alert_start_time):
  193. return "alert"
  194. if (
  195. self.holiday_start_time
  196. and self.holiday_end_time
  197. and self.today >= self.holiday_start_time
  198. and self.today <= self.holiday_end_time
  199. ):
  200. return "holiday"
  201. elif ok or (not self.alert_start_time and self.sr >= 0):
  202. return "ok"
  203. def _get_irregular_status(self):
  204. self.ensure_one()
  205. counter_unsubscribe = int(
  206. self.env["ir.config_parameter"]
  207. .sudo()
  208. .get_param("irregular_counter_to_unsubscribe", -3)
  209. )
  210. alert_delay = int(
  211. self.env["ir.config_parameter"].sudo().get_param("alert_delay", 28)
  212. )
  213. grace_delay = int(
  214. self.env["ir.config_parameter"]
  215. .sudo()
  216. .get_param("default_grace_delay", 10)
  217. )
  218. ok = self.sr >= 0
  219. grace_delay = grace_delay + self.time_extension
  220. if self.sr <= counter_unsubscribe or self.unsubscribed:
  221. return "unsubscribed"
  222. # Check if exempted. Exempt end date is not required.
  223. elif (
  224. # Start and end are defined
  225. self.temporary_exempt_start_date
  226. and self.temporary_exempt_end_date
  227. and self.today >= self.temporary_exempt_start_date
  228. and self.today <= self.temporary_exempt_end_date
  229. ) or (
  230. # Only start is defined
  231. self.temporary_exempt_start_date
  232. and not self.temporary_exempt_end_date
  233. and self.today >= self.temporary_exempt_start_date
  234. ):
  235. return "exempted"
  236. # Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and
  237. # thus alert time is defined
  238. elif (
  239. not ok
  240. and self.alert_start_time
  241. and self.extension_start_time
  242. and self.today
  243. <= add_days_delta(self.extension_start_time, grace_delay)
  244. ):
  245. return "extension"
  246. elif (
  247. not ok
  248. and self.alert_start_time
  249. and self.extension_start_time
  250. and self.today
  251. > add_days_delta(self.extension_start_time, grace_delay)
  252. ):
  253. return "suspended"
  254. elif (
  255. not ok
  256. and self.alert_start_time
  257. and self.today > add_days_delta(self.alert_start_time, alert_delay)
  258. ):
  259. return "suspended"
  260. elif (self.sr < 0) or (not ok and self.alert_start_time):
  261. return "alert"
  262. elif (
  263. self.holiday_start_time
  264. and self.holiday_end_time
  265. and self.today >= self.holiday_start_time
  266. and self.today <= self.holiday_end_time
  267. ):
  268. return "holiday"
  269. elif ok or (not self.alert_start_time and self.sr >= 0):
  270. return "ok"
  271. def _state_change(self, new_state):
  272. self.ensure_one()
  273. if new_state == "alert":
  274. self.write(
  275. {
  276. "alert_start_time": self.today,
  277. "extension_start_time": False,
  278. "time_extension": 0,
  279. }
  280. )
  281. if new_state == "ok":
  282. data = {"extension_start_time": False, "time_extension": 0}
  283. data["alert_start_time"] = False
  284. self.write(data)
  285. if new_state == "unsubscribed" or new_state == "resigning":
  286. # Remove worker from task_templates
  287. self.cooperator_id.sudo().write(
  288. {"subscribed_shift_ids": [(5, 0, 0)]}
  289. )
  290. # Remove worker from supercoop in task_templates
  291. task_tpls = self.env["beesdoo.shift.template"].search(
  292. [("super_coop_id", "in", self.cooperator_id.user_ids.ids)]
  293. )
  294. task_tpls.write({"super_coop_id": False})
  295. # Remove worker for future tasks (remove also supercoop)
  296. self.env["beesdoo.shift.shift"].sudo().unsubscribe_from_today(
  297. [self.cooperator_id.id], now=fields.Datetime.now()
  298. )
  299. def _change_counter(self, data):
  300. """
  301. Call when a shift state is changed
  302. use data generated by _get_counter_date_state_change
  303. """
  304. self.sc += data.get("sc", 0)
  305. self.sr += data.get("sr", 0)
  306. self.irregular_absence_counter += data.get(
  307. "irregular_absence_counter", 0
  308. )
  309. self.irregular_absence_date = data.get("irregular_absence_date", False)
  310. ###############################################
  311. # Irregular Cron implementation #
  312. ###############################################
  313. def _get_irregular_worker_domain(self, **kwargs):
  314. today = kwargs.get("today") or self.today
  315. return [
  316. "&",
  317. "&",
  318. "&",
  319. ("status", "not in", ["unsubscribed", "exempted"]),
  320. ("working_mode", "=", "irregular"),
  321. ("irregular_start_date", "!=", False),
  322. "|",
  323. "|",
  324. ("holiday_start_time", "=", False),
  325. ("holiday_end_time", "=", False),
  326. "|",
  327. ("holiday_start_time", ">", today),
  328. ("holiday_end_time", "<", today),
  329. ]
  330. def _change_irregular_counter(self):
  331. if self.sr > 0:
  332. self.sr -= 1
  333. elif self.alert_start_time:
  334. self.sr -= 1
  335. else:
  336. self.sr -= 2
  337. ##################################
  338. # Internal Implementation #
  339. ##################################
  340. def _next_countdown_date(self, irregular_start_date, today=False):
  341. """
  342. Return the next countdown date given irregular_start_date and
  343. today dates.
  344. This does not take holiday and other status into account.
  345. """
  346. today = today or fields.Date.today()
  347. delta = (today - irregular_start_date).days
  348. if not delta % self._period:
  349. return today
  350. return add_days_delta(today, self._period - (delta % self._period))