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.

363 lines
13 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
  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. self.temporary_exempt_start_date
  157. and self.today >= self.temporary_exempt_start_date
  158. ):
  159. if (
  160. not self.temporary_exempt_end_date
  161. or self.today <= self.temporary_exempt_end_date
  162. ):
  163. return "exempted"
  164. # Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and
  165. # thus alert time is defined
  166. if (
  167. not ok
  168. and self.alert_start_time
  169. and self.extension_start_time
  170. and self.today
  171. <= add_days_delta(self.extension_start_time, grace_delay)
  172. ):
  173. return "extension"
  174. if (
  175. not ok
  176. and self.alert_start_time
  177. and self.extension_start_time
  178. and self.today
  179. > add_days_delta(self.extension_start_time, grace_delay)
  180. ):
  181. return "suspended"
  182. if (
  183. not ok
  184. and self.alert_start_time
  185. and self.today > add_days_delta(self.alert_start_time, alert_delay)
  186. ):
  187. return "suspended"
  188. if (self.sr < 0) or (not ok and self.alert_start_time):
  189. return "alert"
  190. if (
  191. self.holiday_start_time
  192. and self.holiday_end_time
  193. and self.today >= self.holiday_start_time
  194. and self.today <= self.holiday_end_time
  195. ):
  196. return "holiday"
  197. elif ok or (not self.alert_start_time and self.sr >= 0):
  198. return "ok"
  199. def _get_irregular_status(self):
  200. self.ensure_one()
  201. counter_unsubscribe = int(
  202. self.env["ir.config_parameter"]
  203. .sudo()
  204. .get_param("irregular_counter_to_unsubscribe", -3)
  205. )
  206. alert_delay = int(
  207. self.env["ir.config_parameter"].sudo().get_param("alert_delay", 28)
  208. )
  209. grace_delay = int(
  210. self.env["ir.config_parameter"]
  211. .sudo()
  212. .get_param("default_grace_delay", 10)
  213. )
  214. ok = self.sr >= 0
  215. grace_delay = grace_delay + self.time_extension
  216. if self.sr <= counter_unsubscribe or self.unsubscribed:
  217. return "unsubscribed"
  218. # Check if exempted. Exempt end date is not required.
  219. elif (
  220. self.temporary_exempt_start_date
  221. and self.today >= self.temporary_exempt_start_date
  222. ):
  223. if (
  224. not self.temporary_exempt_end_date
  225. or self.today <= self.temporary_exempt_end_date
  226. ):
  227. return "exempted"
  228. # Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and
  229. # thus alert time is defined
  230. elif (
  231. not ok
  232. and self.alert_start_time
  233. and self.extension_start_time
  234. and self.today
  235. <= add_days_delta(self.extension_start_time, grace_delay)
  236. ):
  237. return "extension"
  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 "suspended"
  246. elif (
  247. not ok
  248. and self.alert_start_time
  249. and self.today > add_days_delta(self.alert_start_time, alert_delay)
  250. ):
  251. return "suspended"
  252. elif (self.sr < 0) or (not ok and self.alert_start_time):
  253. return "alert"
  254. elif (
  255. self.holiday_start_time
  256. and self.holiday_end_time
  257. and self.today >= self.holiday_start_time
  258. and self.today <= self.holiday_end_time
  259. ):
  260. return "holiday"
  261. elif ok or (not self.alert_start_time and self.sr >= 0):
  262. return "ok"
  263. def _state_change(self, new_state):
  264. self.ensure_one()
  265. if new_state == "alert":
  266. self.write(
  267. {
  268. "alert_start_time": self.today,
  269. "extension_start_time": False,
  270. "time_extension": 0,
  271. }
  272. )
  273. if new_state == "ok":
  274. data = {"extension_start_time": False, "time_extension": 0}
  275. data["alert_start_time"] = False
  276. self.write(data)
  277. if new_state == "unsubscribed" or new_state == "resigning":
  278. # Remove worker from task_templates
  279. self.cooperator_id.sudo().write(
  280. {"subscribed_shift_ids": [(5, 0, 0)]}
  281. )
  282. # Remove worker from supercoop in task_templates
  283. task_tpls = self.env["beesdoo.shift.template"].search(
  284. [("super_coop_id", "in", self.cooperator_id.user_ids.ids)]
  285. )
  286. task_tpls.write({"super_coop_id": False})
  287. # Remove worker for future tasks (remove also supercoop)
  288. self.env["beesdoo.shift.shift"].sudo().unsubscribe_from_today(
  289. [self.cooperator_id.id], now=fields.Datetime.now()
  290. )
  291. def _change_counter(self, data):
  292. """
  293. Call when a shift state is changed
  294. use data generated by _get_counter_date_state_change
  295. """
  296. self.sc += data.get("sc", 0)
  297. self.sr += data.get("sr", 0)
  298. self.irregular_absence_counter += data.get(
  299. "irregular_absence_counter", 0
  300. )
  301. self.irregular_absence_date = data.get("irregular_absence_date", False)
  302. ###############################################
  303. ###### Irregular Cron implementation ##########
  304. ###############################################
  305. def _get_irregular_worker_domain(self, **kwargs):
  306. today = kwargs.get("today") or self.today
  307. return [
  308. "&",
  309. "&",
  310. "&",
  311. ("status", "not in", ["unsubscribed", "exempted"]),
  312. ("working_mode", "=", "irregular"),
  313. ("irregular_start_date", "!=", False),
  314. "|",
  315. "|",
  316. ("holiday_start_time", "=", False),
  317. ("holiday_end_time", "=", False),
  318. "|",
  319. ("holiday_start_time", ">", today),
  320. ("holiday_end_time", "<", today),
  321. ]
  322. def _change_irregular_counter(self):
  323. if self.sr > 0:
  324. self.sr -= 1
  325. elif self.alert_start_time:
  326. self.sr -= 1
  327. else:
  328. self.sr -= 2
  329. ##################################
  330. # Internal Implementation #
  331. ##################################
  332. def _next_countdown_date(self, irregular_start_date, today=False):
  333. """
  334. Return the next countdown date given irregular_start_date and
  335. today dates.
  336. This does not take holiday and other status into account.
  337. """
  338. today = today or fields.Date.today()
  339. delta = (today - irregular_start_date).days
  340. if not delta % self._period:
  341. return today
  342. return add_days_delta(today, self._period - (delta % self._period))