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.

277 lines
14 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
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. # © 2019 Le Filament (<http://www.le-filament.com>)
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  3. from odoo import models, fields, api
  4. from dateutil.rrule import rrule, DAILY, MINUTELY
  5. from dateutil.relativedelta import relativedelta
  6. from datetime import datetime, timedelta
  7. from pytz import timezone
  8. class VracoopPointRetrait(models.Model):
  9. _name = "vracoop.point.retrait"
  10. _description = "Point de retrait"
  11. _inherit = ['website.published.multi.mixin']
  12. @api.model
  13. def default_get(self, fields):
  14. res = super(VracoopPointRetrait, self).default_get(fields)
  15. vracoop_time_ids = self.env['vracoop.time'].search([])
  16. vracoop_retrait_time_ids = []
  17. for vracoop_time_id in vracoop_time_ids:
  18. if vracoop_time_id.name == 6 or vracoop_time_id.name == 0:
  19. active_day = False
  20. else:
  21. active_day = True
  22. vals = {
  23. 'vracoop_time_id': vracoop_time_id.id,
  24. 'name': int(vracoop_time_id.name),
  25. 'first_morning_heure': vracoop_time_id.first_morning_heure,
  26. 'last_morning_heure': vracoop_time_id.last_morning_heure,
  27. 'first_noon_heure': vracoop_time_id.first_noon_heure,
  28. 'last_noon_heure': vracoop_time_id.last_noon_heure,
  29. 'preparation_time': vracoop_time_id.preparation_time,
  30. 'availability_time': vracoop_time_id.availability_time,
  31. 'active_day': active_day
  32. }
  33. vracoop_retrait_time_ids.append((0, 0, vals))
  34. res.update({'vracoop_retrait_time_ids': vracoop_retrait_time_ids})
  35. return res
  36. name = fields.Char("Nom du point relais")
  37. active = fields.Boolean(default=True)
  38. street = fields.Char()
  39. street2 = fields.Char()
  40. zip = fields.Char(change_default=True)
  41. city = fields.Char()
  42. state_id = fields.Many2one(
  43. "res.country.state",
  44. string='State',
  45. ondelete='restrict',
  46. domain="[('country_id', '=?', country_id)]")
  47. country_id = fields.Many2one(
  48. 'res.country', string='Country', ondelete='restrict')
  49. image = fields.Binary("Image", attachment=True,)
  50. image_medium = fields.Binary("Medium-sized image", attachment=True)
  51. image_small = fields.Binary("Small-sized image", attachment=True)
  52. vracoop_retrait_time_ids = fields.One2many(
  53. comodel_name='vracoop.retrait.time',
  54. inverse_name='vracoop_point_retrait_id',
  55. string="Configuration des horaires")
  56. nb_max_retrait = fields.Integer(
  57. "Nombre de retrait max par tranche horaire")
  58. nb_day_available = fields.Integer(
  59. "Nombre de jours pour commande", default=7)
  60. nb_hours_preparation = fields.Float(
  61. "Nombre d'heures de préparation", default=0.0)
  62. @api.multi
  63. def slot_calculate(self):
  64. self.ensure_one()
  65. LIST_WEEK_DAY = [
  66. ('lundi', 0, 1, 'lun.'),
  67. ('mardi', 1, 2, 'mar.'),
  68. ('mercredi', 2, 3, 'mer.'),
  69. ('jeudi', 3, 4, 'jeu.'),
  70. ('vendredi', 4, 5, 'ven.'),
  71. ('samedi', 5, 6, 'sam.'),
  72. ('dimanche', 6, 0, 'dim.'),
  73. ]
  74. for rec in self:
  75. today_datetime_utc = datetime.now(timezone('UTC'))
  76. today_datetime2 = today_datetime_utc.astimezone(timezone('Europe/Berlin'))
  77. today_datetime = datetime(
  78. today_datetime2.year,
  79. today_datetime2.month,
  80. today_datetime2.day,
  81. today_datetime2.hour,
  82. today_datetime2.minute,
  83. today_datetime2.second)
  84. # today_datetime = datetime.strptime(today_datetime2, "%Y-%m-%d %H:%M:%S")
  85. return_slot_list = []
  86. vals = []
  87. exclure_days_nb = rec.vracoop_retrait_time_ids.search_count([
  88. ('vracoop_point_retrait_id', '=', rec.id),
  89. ('active_day', '=', False)])
  90. count_day = rec.nb_day_available + exclure_days_nb
  91. # Liste des jours où je peux récupérer la commande
  92. # en fonction nombre de jour dispo sur la fiche du point retrait
  93. first_day = datetime.today() + relativedelta(hours=rec.nb_hours_preparation)
  94. list_week = list(rrule(
  95. DAILY,
  96. count=count_day,
  97. dtstart=first_day))
  98. for week in list_week:
  99. # On exclut les jours où la journée
  100. # du point de retrait n'est pas actif
  101. exclure_the_day = rec.vracoop_retrait_time_ids.search([
  102. ('vracoop_point_retrait_id', '=', rec.id),
  103. ('active_day', '=', False),
  104. ('name', '=', week.strftime("%w"))])
  105. if exclure_the_day:
  106. pass
  107. else:
  108. # Récupération de la ligne du jour correpsondant
  109. corresponding_line = rec.vracoop_retrait_time_ids.search([
  110. ('vracoop_point_retrait_id', '=', rec.id),
  111. ('name', '=', week.strftime("%w"))])
  112. # Récupération du nom du jour et du Short name du jour
  113. for week_day in LIST_WEEK_DAY:
  114. if week_day[2] == int(week.strftime("%w")):
  115. byweekday = week_day[1]
  116. day_short_name = week_day[3]
  117. # Calcul de l'heure à laquelle la commande est disponible
  118. time_available_week = datetime(
  119. week.year, week.month, week.day) + timedelta(
  120. hours=corresponding_line.availability_time)
  121. hour = time_available_week.strftime("%H")
  122. minute = time_available_week.strftime("%M")
  123. interval = int(hour)*60 + int(minute)
  124. first_morning_hour_week = datetime(
  125. week.year, week.month, week.day) + timedelta(
  126. hours=corresponding_line.first_morning_heure)
  127. last_morning_hour_week = datetime(
  128. week.year, week.month, week.day) + timedelta(
  129. hours=corresponding_line.last_morning_heure)
  130. first_noon_hour_week = datetime(
  131. week.year, week.month, week.day) + timedelta(
  132. hours=corresponding_line.first_noon_heure)
  133. last_noon_hour_week = datetime(
  134. week.year, week.month, week.day) + timedelta(
  135. hours=corresponding_line.last_noon_heure)
  136. # Calcul des Slots (matin et après-midi) par jour en
  137. # fonction de l'intervalle (correspondant au temps de mis
  138. # à disposition) et des dates de début et de fin de retrait
  139. list_slot_per_day_morning = list(
  140. rrule(
  141. MINUTELY,
  142. interval=interval,
  143. byweekday=byweekday,
  144. dtstart=first_morning_hour_week,
  145. until=last_morning_hour_week))
  146. list_slot_per_day_noon = list(
  147. rrule(
  148. MINUTELY, interval=interval,
  149. byweekday=byweekday,
  150. dtstart=first_noon_hour_week,
  151. until=last_noon_hour_week))
  152. slots = []
  153. nb_sale_slot = 0
  154. # Heure disponible pour un retrait
  155. # en fonction du temps de préparation
  156. today_hour_available = today_datetime + timedelta(
  157. hours=(corresponding_line.preparation_time + rec.nb_hours_preparation))
  158. # Boucle pour les créneaux du matin
  159. for slot_elem in list_slot_per_day_morning:
  160. # Conversion du 1er Slot en HH:MM
  161. first_slot = slot_elem.strftime("%H:%M")
  162. # Calcul du dernier slot
  163. # en fonction du temps de mis à dsiposition
  164. slot_elem_last = slot_elem + timedelta(
  165. hours=corresponding_line.availability_time)
  166. # Conversion du Dernier Slot en HH:MM
  167. last_slot = slot_elem_last.strftime("%H:%M")
  168. if slot_elem >= last_morning_hour_week:
  169. continue
  170. if slot_elem_last >= last_morning_hour_week:
  171. slot_elem_last = last_morning_hour_week
  172. last_slot = slot_elem_last.strftime("%H:%M")
  173. # Si le jour est égal à la date du jour
  174. day_first = today_datetime.date() + relativedelta(hours=rec.nb_hours_preparation)
  175. if slot_elem.date() == day_first:
  176. if (slot_elem_last > last_morning_hour_week):
  177. if (today_hour_available > last_morning_hour_week):
  178. continue
  179. if (today_hour_available > slot_elem_last):
  180. continue
  181. if (today_hour_available > slot_elem):
  182. slot_elem_first = today_hour_available + timedelta(
  183. hours=1.0)
  184. first_slot = slot_elem_first.strftime("%H:00")
  185. if first_slot == last_slot:
  186. continue
  187. # Vérification si
  188. # Nombre max de retrait défini a été atteint
  189. # Pas de controle si La valeur définie est 0
  190. if rec.nb_max_retrait > 0:
  191. first_slot_hour = first_slot.split(":")
  192. first_slot_float = float(
  193. '%s.%s' % (first_slot_hour[0], first_slot_hour[1]))
  194. nb_sale_slot = self.env['sale.order'].search_count(
  195. [('vracoop_point_retrait_id', '=', rec.id),
  196. ('day_retrait', '=', week.date()),
  197. ('hour_retrait', '=', first_slot_float)])
  198. if nb_sale_slot < rec.nb_max_retrait:
  199. slots.append((first_slot, last_slot))
  200. else:
  201. slots.append((first_slot, last_slot))
  202. # Boucle pour les créneaux de l'après-midi
  203. for slot_elem in list_slot_per_day_noon:
  204. # Conversion du 1er Slot en HH:MM
  205. first_slot = slot_elem.strftime("%H:%M")
  206. # Calcul du dernier slot
  207. # en fonction du temps de mis à dsiposition
  208. slot_elem_last = slot_elem + timedelta(
  209. hours=corresponding_line.availability_time)
  210. # Conversion du Dernier Slot en HH:MM
  211. last_slot = slot_elem_last.strftime("%H:%M")
  212. if slot_elem >= last_noon_hour_week:
  213. continue
  214. if slot_elem_last >= last_noon_hour_week:
  215. slot_elem_last = last_noon_hour_week
  216. last_slot = slot_elem_last.strftime("%H:%M")
  217. # Si le jour est égal à la date du jour
  218. if slot_elem.date() == today_datetime.date():
  219. if (slot_elem_last > last_noon_hour_week):
  220. if (today_hour_available > last_noon_hour_week):
  221. continue
  222. if (today_hour_available > slot_elem_last):
  223. continue
  224. if (today_hour_available > slot_elem):
  225. slot_elem_first = today_hour_available + timedelta(
  226. hours=1.0)
  227. first_slot = slot_elem_first.strftime("%H:00")
  228. if first_slot == last_slot:
  229. continue
  230. # Vérification si
  231. # Nombre max de retrait défini a été atteint
  232. # Pas de controle si La valeur définie est 0
  233. if rec.nb_max_retrait > 0:
  234. first_slot_hour = first_slot.split(":")
  235. first_slot_float = float(
  236. '%s.%s' % (first_slot_hour[0], first_slot_hour[1]))
  237. nb_sale_slot = self.env['sale.order'].search_count(
  238. [('vracoop_point_retrait_id', '=', rec.id),
  239. ('day_retrait', '=', week.date()),
  240. ('hour_retrait', '=', first_slot_float)])
  241. if nb_sale_slot < rec.nb_max_retrait:
  242. slots.append((first_slot, last_slot))
  243. else:
  244. slots.append((first_slot, last_slot))
  245. return_slot_list = slots
  246. if return_slot_list:
  247. vals.append(
  248. (day_short_name,
  249. week,
  250. week.strftime("%b"), return_slot_list))
  251. return vals