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.

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