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.

269 lines
9.5 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
[ADD] Improve Shift management après avoir généré les shifts pour une semaine, rediriger vers les shifts générés : ok Ajouter un supercoopérateur au niveau du template de shift. Pas de champs related car il faut pouvoir gérer les remplacements entre supercoopérateurs. : Rajouter un boolean sur res.users pour dire qu'ils sont super coopérateur du coup on peut choisir qu'un utilisateur super coopérateur : Ok Sur la vue des shifts, permettre de sélectionner un ensemble de shifts pour pouvoir changer son supercoopérateur en une action : Ok Avoir une vue des shifts par défaut plus lisible que le calendrier : KANBAN avec TODAY par défaut et les colonnes selon le type de shift : ok Dans la vue KANBAN du planning des semaines, faire un tri sur la start date pour que ça ressemble à une vue calendrier :ok Droits d'accès : 3 groupes : modifier un shift existant et confirmer son statut : absence/présence générer et supprimer des shifts à partir du template modifier le template des semaines et gérer la config En réfléchissant à ceux qui vont gérer les présences : il faudrait avoir une vue facile sur les shifts du jour et une manière simple de dire présent/absent/remplacé pour l'ensemble des coopérateurs présents (éviter de devoir chaque fois sélectionner le shift, cliquer sur le statut, aller au shift suivant, cliquer sur le statut...). J'ai fait un nouveau point de menu avec une vue Kanban grouper par status, il suffit de faire du drag and drop pour changer le status, les shifts sont aussi filtré sur aujourd'hui et seulement ceux ayant un worker assigné.
8 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
[ADD] Improve Shift management après avoir généré les shifts pour une semaine, rediriger vers les shifts générés : ok Ajouter un supercoopérateur au niveau du template de shift. Pas de champs related car il faut pouvoir gérer les remplacements entre supercoopérateurs. : Rajouter un boolean sur res.users pour dire qu'ils sont super coopérateur du coup on peut choisir qu'un utilisateur super coopérateur : Ok Sur la vue des shifts, permettre de sélectionner un ensemble de shifts pour pouvoir changer son supercoopérateur en une action : Ok Avoir une vue des shifts par défaut plus lisible que le calendrier : KANBAN avec TODAY par défaut et les colonnes selon le type de shift : ok Dans la vue KANBAN du planning des semaines, faire un tri sur la start date pour que ça ressemble à une vue calendrier :ok Droits d'accès : 3 groupes : modifier un shift existant et confirmer son statut : absence/présence générer et supprimer des shifts à partir du template modifier le template des semaines et gérer la config En réfléchissant à ceux qui vont gérer les présences : il faudrait avoir une vue facile sur les shifts du jour et une manière simple de dire présent/absent/remplacé pour l'ensemble des coopérateurs présents (éviter de devoir chaque fois sélectionner le shift, cliquer sur le statut, aller au shift suivant, cliquer sur le statut...). J'ai fait un nouveau point de menu avec une vue Kanban grouper par status, il suffit de faire du drag and drop pour changer le status, les shifts sont aussi filtré sur aujourd'hui et seulement ceux ayant un worker assigné.
8 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
[ADD] Improve Shift management après avoir généré les shifts pour une semaine, rediriger vers les shifts générés : ok Ajouter un supercoopérateur au niveau du template de shift. Pas de champs related car il faut pouvoir gérer les remplacements entre supercoopérateurs. : Rajouter un boolean sur res.users pour dire qu'ils sont super coopérateur du coup on peut choisir qu'un utilisateur super coopérateur : Ok Sur la vue des shifts, permettre de sélectionner un ensemble de shifts pour pouvoir changer son supercoopérateur en une action : Ok Avoir une vue des shifts par défaut plus lisible que le calendrier : KANBAN avec TODAY par défaut et les colonnes selon le type de shift : ok Dans la vue KANBAN du planning des semaines, faire un tri sur la start date pour que ça ressemble à une vue calendrier :ok Droits d'accès : 3 groupes : modifier un shift existant et confirmer son statut : absence/présence générer et supprimer des shifts à partir du template modifier le template des semaines et gérer la config En réfléchissant à ceux qui vont gérer les présences : il faudrait avoir une vue facile sur les shifts du jour et une manière simple de dire présent/absent/remplacé pour l'ensemble des coopérateurs présents (éviter de devoir chaque fois sélectionner le shift, cliquer sur le statut, aller au shift suivant, cliquer sur le statut...). J'ai fait un nouveau point de menu avec une vue Kanban grouper par status, il suffit de faire du drag and drop pour changer le status, les shifts sont aussi filtré sur aujourd'hui et seulement ceux ayant un worker assigné.
8 years ago
5 years ago
5 years ago
5 years ago
[ADD] Improve Shift management après avoir généré les shifts pour une semaine, rediriger vers les shifts générés : ok Ajouter un supercoopérateur au niveau du template de shift. Pas de champs related car il faut pouvoir gérer les remplacements entre supercoopérateurs. : Rajouter un boolean sur res.users pour dire qu'ils sont super coopérateur du coup on peut choisir qu'un utilisateur super coopérateur : Ok Sur la vue des shifts, permettre de sélectionner un ensemble de shifts pour pouvoir changer son supercoopérateur en une action : Ok Avoir une vue des shifts par défaut plus lisible que le calendrier : KANBAN avec TODAY par défaut et les colonnes selon le type de shift : ok Dans la vue KANBAN du planning des semaines, faire un tri sur la start date pour que ça ressemble à une vue calendrier :ok Droits d'accès : 3 groupes : modifier un shift existant et confirmer son statut : absence/présence générer et supprimer des shifts à partir du template modifier le template des semaines et gérer la config En réfléchissant à ceux qui vont gérer les présences : il faudrait avoir une vue facile sur les shifts du jour et une manière simple de dire présent/absent/remplacé pour l'ensemble des coopérateurs présents (éviter de devoir chaque fois sélectionner le shift, cliquer sur le statut, aller au shift suivant, cliquer sur le statut...). J'ai fait un nouveau point de menu avec une vue Kanban grouper par status, il suffit de faire du drag and drop pour changer le status, les shifts sont aussi filtré sur aujourd'hui et seulement ceux ayant un worker assigné.
8 years ago
5 years ago
5 years ago
5 years ago
[ADD] Improve Shift management après avoir généré les shifts pour une semaine, rediriger vers les shifts générés : ok Ajouter un supercoopérateur au niveau du template de shift. Pas de champs related car il faut pouvoir gérer les remplacements entre supercoopérateurs. : Rajouter un boolean sur res.users pour dire qu'ils sont super coopérateur du coup on peut choisir qu'un utilisateur super coopérateur : Ok Sur la vue des shifts, permettre de sélectionner un ensemble de shifts pour pouvoir changer son supercoopérateur en une action : Ok Avoir une vue des shifts par défaut plus lisible que le calendrier : KANBAN avec TODAY par défaut et les colonnes selon le type de shift : ok Dans la vue KANBAN du planning des semaines, faire un tri sur la start date pour que ça ressemble à une vue calendrier :ok Droits d'accès : 3 groupes : modifier un shift existant et confirmer son statut : absence/présence générer et supprimer des shifts à partir du template modifier le template des semaines et gérer la config En réfléchissant à ceux qui vont gérer les présences : il faudrait avoir une vue facile sur les shifts du jour et une manière simple de dire présent/absent/remplacé pour l'ensemble des coopérateurs présents (éviter de devoir chaque fois sélectionner le shift, cliquer sur le statut, aller au shift suivant, cliquer sur le statut...). J'ai fait un nouveau point de menu avec une vue Kanban grouper par status, il suffit de faire du drag and drop pour changer le status, les shifts sont aussi filtré sur aujourd'hui et seulement ceux ayant un worker assigné.
8 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. import math
  2. from datetime import datetime, time, timedelta
  3. from pytz import UTC, timezone
  4. from odoo import _, api, fields, models
  5. from odoo.exceptions import UserError
  6. def float_to_time(f):
  7. decimal, integer = math.modf(f)
  8. return "{}:{}".format(
  9. str(int(integer)).zfill(2), str(int(round(decimal * 60))).zfill(2)
  10. )
  11. def floatime_to_hour_minute(f):
  12. decimal, integer = math.modf(f)
  13. return int(integer), int(round(decimal * 60))
  14. def get_first_day_of_week():
  15. today = datetime.now()
  16. return (datetime.now() - timedelta(days=today.weekday())).date()
  17. class TaskType(models.Model):
  18. _name = "beesdoo.shift.type"
  19. _description = "beesdoo.shift.type"
  20. name = fields.Char()
  21. description = fields.Text()
  22. active = fields.Boolean(default=True)
  23. class DayNumber(models.Model):
  24. _name = "beesdoo.shift.daynumber"
  25. _description = "beesdoo.shift.daynumber"
  26. _order = "number asc"
  27. name = fields.Char()
  28. number = fields.Integer(
  29. "Day Number",
  30. help="From 1 to N, When you will instanciate your planning, Day 1 will be the start date of the instance, Day 2 the second, etc...",
  31. )
  32. active = fields.Boolean(default=True)
  33. class Planning(models.Model):
  34. _name = "beesdoo.shift.planning"
  35. _description = "beesdoo.shift.planning"
  36. _order = "sequence asc"
  37. sequence = fields.Integer()
  38. name = fields.Char()
  39. task_template_ids = fields.One2many(
  40. "beesdoo.shift.template", "planning_id"
  41. )
  42. @api.model
  43. def _get_next_planning(self, sequence):
  44. next_planning = self.search([("sequence", ">", sequence)])
  45. if not next_planning:
  46. return self.search([])[0]
  47. return next_planning[0]
  48. @api.multi
  49. def _get_next_planning_date(self, date):
  50. self.ensure_one()
  51. nb_of_day = max(self.task_template_ids.mapped("day_nb_id.number"))
  52. return date + timedelta(days=nb_of_day)
  53. @api.model
  54. def _generate_next_planning(self):
  55. config = self.env["ir.config_parameter"].sudo()
  56. last_seq = int(config.get_param("last_planning_seq", 0))
  57. date = fields.Date.from_string(
  58. config.get_param("next_planning_date", 0)
  59. )
  60. planning = self._get_next_planning(last_seq)
  61. planning = planning.with_context(visualize_date=date)
  62. planning.task_template_ids._generate_task_day()
  63. next_date = planning._get_next_planning_date(date)
  64. config.set_param("last_planning_seq", planning.sequence)
  65. config.set_param("next_planning_date", next_date)
  66. class TaskTemplate(models.Model):
  67. _name = "beesdoo.shift.template"
  68. _description = "beesdoo.shift.template"
  69. _order = "start_time"
  70. name = fields.Char(required=True)
  71. planning_id = fields.Many2one("beesdoo.shift.planning", required=True)
  72. day_nb_id = fields.Many2one(
  73. "beesdoo.shift.daynumber", string="Day", required=True
  74. )
  75. task_type_id = fields.Many2one("beesdoo.shift.type", string="Type")
  76. # attendance_sheet_id = fields.Many2one('beesdoo.shift.sheet', string="Attendance Sheet") FIXME removed because beesdoo.shift.sheet is from another module.
  77. start_time = fields.Float(required=True)
  78. end_time = fields.Float(required=True)
  79. super_coop_id = fields.Many2one(
  80. "res.users",
  81. string="Super Cooperative",
  82. domain=[("partner_id.super", "=", True)],
  83. )
  84. duration = fields.Float(help="Duration in Hour")
  85. worker_nb = fields.Integer(
  86. string="Number of worker",
  87. help="Max number of worker for this task",
  88. default=1,
  89. )
  90. worker_ids = fields.Many2many(
  91. "res.partner",
  92. string="Recurrent worker assigned",
  93. domain=[("is_worker", "=", True)],
  94. )
  95. remaining_worker = fields.Integer(
  96. compute="_compute_remaining", store=True, string="Remaining Place"
  97. )
  98. active = fields.Boolean(default=True)
  99. # For Kanban View Only
  100. color = fields.Integer("Color Index")
  101. worker_name = fields.Char(compute="_compute_worker_name")
  102. # For calendar View
  103. start_date = fields.Datetime(
  104. compute="_compute_fake_date", search="_search_dummy"
  105. )
  106. end_date = fields.Datetime(
  107. compute="_compute_fake_date", search="_search_dummy"
  108. )
  109. def _get_utc_date(self, day, hour, minute):
  110. """Combine day number, hours and minutes to save
  111. corresponding UTC datetime in database.
  112. """
  113. context_tz = timezone(self._context.get("tz") or self.env.user.tz)
  114. day_local_time = datetime.combine(day, time(hour=hour, minute=minute))
  115. day_local_time = context_tz.localize(day_local_time)
  116. day_utc_time = day_local_time.astimezone(UTC)
  117. # Return naïve datetime so as to be saved in database
  118. return day_utc_time.replace(tzinfo=None)
  119. @api.depends("start_time", "end_time")
  120. def _compute_fake_date(self):
  121. today = self._context.get("visualize_date", get_first_day_of_week())
  122. for rec in self:
  123. # Find the day of this task template 'rec'.
  124. day = today + timedelta(days=rec.day_nb_id.number - 1)
  125. # Compute the beginning and ending time according to the
  126. # context timezone.
  127. h_begin, m_begin = floatime_to_hour_minute(rec.start_time)
  128. h_end, m_end = floatime_to_hour_minute(rec.end_time)
  129. rec.start_date = self._get_utc_date(day, h_begin, m_begin)
  130. rec.end_date = self._get_utc_date(day, h_end, m_end)
  131. def _search_dummy(self, operator, value):
  132. return []
  133. @api.depends("worker_ids", "worker_nb")
  134. def _compute_remaining(self):
  135. for rec in self:
  136. rec.remaining_worker = rec.worker_nb - len(rec.worker_ids)
  137. @api.depends("worker_ids")
  138. def _compute_worker_name(self):
  139. for rec in self:
  140. rec.worker_name = ",".join(rec.worker_ids.mapped("display_name"))
  141. @api.constrains("worker_nb", "worker_ids")
  142. def _nb_worker_max(self):
  143. for rec in self:
  144. if len(rec.worker_ids) > rec.worker_nb:
  145. raise UserError(
  146. _(
  147. "You cannot assign more workers than the maximal number defined on template."
  148. )
  149. )
  150. @api.onchange("start_time", "end_time")
  151. def _get_duration(self):
  152. if self.start_time and self.end_time:
  153. self.duration = self.end_time - self.start_time
  154. @api.onchange("duration")
  155. def _set_duration(self):
  156. if self.start_time:
  157. self.end_time = self.start_time + self.duration
  158. def _generate_task_day(self):
  159. tasks = self.env["beesdoo.shift.shift"]
  160. for rec in self:
  161. for i in range(0, rec.worker_nb):
  162. worker_id = (
  163. rec.worker_ids[i] if len(rec.worker_ids) > i else False
  164. )
  165. # remove worker in holiday and temporary exempted
  166. if worker_id and worker_id.cooperative_status_ids:
  167. status = worker_id.cooperative_status_ids[0]
  168. if (
  169. status.holiday_start_time
  170. and status.holiday_end_time
  171. and status.holiday_start_time <= rec.start_date.date()
  172. and status.holiday_end_time >= rec.end_date.date()
  173. ):
  174. worker_id = False
  175. if (
  176. status.temporary_exempt_start_date
  177. and status.temporary_exempt_end_date
  178. and status.temporary_exempt_start_date
  179. <= rec.start_date.date()
  180. and status.temporary_exempt_end_date
  181. >= rec.end_date.date()
  182. ):
  183. worker_id = False
  184. tasks |= tasks.create(
  185. {
  186. "name": "[%s] %s %s (%s - %s) [%s]"
  187. % (
  188. rec.start_date.date(),
  189. rec.planning_id.name,
  190. rec.day_nb_id.name,
  191. float_to_time(rec.start_time),
  192. float_to_time(rec.end_time),
  193. i,
  194. ),
  195. "task_template_id": rec.id,
  196. "task_type_id": rec.task_type_id.id,
  197. "super_coop_id": rec.super_coop_id.id,
  198. "worker_id": worker_id and worker_id.id or False,
  199. "is_regular": True if worker_id else False,
  200. "start_time": rec.start_date,
  201. "end_time": rec.end_date,
  202. "state": "open",
  203. }
  204. )
  205. return tasks
  206. @api.onchange("worker_ids")
  207. def check_for_multiple_shifts(self):
  208. original_ids = {worker.id for worker in self._origin.worker_ids}
  209. warnings = []
  210. for worker in self.worker_ids:
  211. if worker.id not in original_ids:
  212. shifts = [
  213. shift.name
  214. for shift in worker.subscribed_shift_ids
  215. if shift.id != self.id
  216. ]
  217. if shifts:
  218. warnings.append(
  219. worker.name
  220. + _(" is already assigned to ")
  221. + ", ".join(shifts)
  222. )
  223. if warnings:
  224. return {
  225. "warning": {
  226. "title": _("Warning"),
  227. "message": "\n".join(warnings),
  228. }
  229. }