plages libres, permettre la mise à jour des plages d'une semaine type #78084 #101

Merged
vdeniaud merged 2 commits from wip/78084-plages-libres-permettre-la-mise- into main 2023-07-04 13:29:46 +02:00
2 changed files with 87 additions and 13 deletions

View File

@ -1733,19 +1733,20 @@ class RecurringFillslots(APIView):
)
events_to_book = events_to_book.exclude(has_overlap=True)
existing_bookings = Booking.objects.filter(
event__in=events_to_book, user_external_id=user_external_id
).values('event')
# outdated bookings to remove (cancelled bookings to replace by an active booking)
events_cancelled_to_delete = events_to_book.filter(
booking__user_external_id=user_external_id,
booking__cancellation_datetime__isnull=False,
pk__in=existing_bookings.filter(
Q(cancellation_datetime__isnull=False) | Q(start_time__isnull=False)
),
full=False,
)
# book only events without active booking for the user
events_to_book = events_to_book.exclude(
pk__in=Booking.objects.filter(
event__in=events_to_book,
user_external_id=user_external_id,
cancellation_datetime__isnull=True,
).values('event')
pk__in=existing_bookings.filter(cancellation_datetime__isnull=True, start_time__isnull=True),
)
# exclude full events
@ -1774,11 +1775,6 @@ class RecurringFillslots(APIView):
events_by_id = {x.id: x for x in list(events_to_book) + list(events_to_unbook)}
with transaction.atomic():
# cancel existing bookings
cancellation_datetime = now()
Booking.objects.filter(primary_booking__in=bookings_to_cancel).update(
cancellation_datetime=cancellation_datetime
)
if payload.get('include_booked_events_detail'):
cancelled_events = [
get_short_event_detail(
@ -1788,7 +1784,15 @@ class RecurringFillslots(APIView):
)
for x in bookings_to_cancel
]
cancelled_count = bookings_to_cancel.update(cancellation_datetime=cancellation_datetime)
if not payload.get('start_time'):
# cancel existing bookings
cancellation_datetime = now()
Booking.objects.filter(primary_booking__in=bookings_to_cancel).update(
cancellation_datetime=cancellation_datetime
)
cancelled_count = bookings_to_cancel.update(cancellation_datetime=cancellation_datetime)
else:
cancelled_count, dummy = bookings_to_cancel.delete()
# and delete outdated cancelled bookings
Booking.objects.filter(
user_external_id=user_external_id, event__in=events_cancelled_to_delete

View File

@ -1737,3 +1737,73 @@ def test_recurring_events_api_fillslots_partial_bookings(app, user):
params['end_time'] = '09:00'
resp = app.post_json(fillslots_url, params=params, status=400)
assert resp.json['errors']['non_field_errors'][0] == 'start_time must be before end_time'
@pytest.mark.freeze_time('2023-05-01 10:00')
def test_recurring_events_api_fillslots_partial_bookings_update(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
event = Event.objects.create(
label='Event 08-18',
start_datetime=start_datetime,
end_time=datetime.time(18, 00),
places=2,
recurrence_end_date=start_datetime + datetime.timedelta(days=30),
recurrence_days=[1, 2],
agenda=agenda,
)
event.create_all_recurrences()
app.authorization = ('Basic', ('john.doe', 'password'))
params = {
'user_external_id': 'user_id',
'slots': 'foo-bar@event-08-18:1',
'start_time': '10:00',
'end_time': '15:00',
}
fillslots_url = '/api/agendas/recurring-events/fillslots/?action=update&agendas=%s' % agenda.slug
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 5
assert Booking.objects.count() == 5
assert (
Booking.objects.filter(
start_time=datetime.time(10, 00),
end_time=datetime.time(15, 00),
event__start_datetime__week_day=3,
).count()
== 5
)
params['start_time'] = '10:00'
params['end_time'] = '15:00'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 5
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.count() == 5
assert (
Booking.objects.filter(
cancellation_datetime__isnull=True,
start_time=datetime.time(10, 00),
end_time=datetime.time(15, 00),
event__start_datetime__week_day=3,
).count()
== 5
)
# change day
params['slots'] = 'foo-bar@event-08-18:2'
resp = app.post_json(fillslots_url, params=params)
assert resp.json['booking_count'] == 5

On suit le comportement ajouté par #61066, on se retrouve donc avec un historique des réservations annulées en base. Il faudrait remonter au besoin fonctionnel qui a conduit à #61066 pour statuer ici ?

On suit le comportement ajouté par #61066, on se retrouve donc avec un historique des réservations annulées en base. Il faudrait remonter au besoin fonctionnel qui a conduit à #61066 pour statuer ici ?

On garde les annulations, parce qu'on a besoin de remonter cette info dans le calendrier (la superbe couleur jaune)

On garde les annulations, parce qu'on a besoin de remonter cette info dans le calendrier (la superbe couleur jaune)

Mais il faudrait demander à stef et/ou cédric, dans quel cas, pour des rdv crèche, on veut voir remonter des annulations dans le calendrier (les points suivants sont exclusifs):

  • toute modif de plage horaire ? exemple: avant on avait 9H-17H, mais ça a été modifié en 8H-18H, donc le créneau 9H-17H apparaît en jaune, l'autre en vert ? (<- j'ai l'impression que le code fait ça ?)
  • toute modif qui raccourcit une borne ? exemple: avant on avait 8H-18H, mais ça a été modifié en 9H-18H, on voit 8H-9H en jaune, le reste en vert ?
  • une modif qui fait que pour une journée donnée, tout est annulé ? exemple: on avait du 9H-18H, ça a été modifié pour annuler complètement cette journée, on voit 9H-18H en jaune ?
  • les annulations ne sont pas affichées ?
Mais il faudrait demander à stef et/ou cédric, dans quel cas, pour des rdv crèche, on veut voir remonter des annulations dans le calendrier (les points suivants sont exclusifs): - toute modif de plage horaire ? exemple: avant on avait 9H-17H, mais ça a été modifié en 8H-18H, donc le créneau 9H-17H apparaît en jaune, l'autre en vert ? (<- j'ai l'impression que le code fait ça ?) - toute modif qui raccourcit une borne ? exemple: avant on avait 8H-18H, mais ça a été modifié en 9H-18H, on voit 8H-9H en jaune, le reste en vert ? - une modif qui fait que pour une journée donnée, tout est annulé ? exemple: on avait du 9H-18H, ça a été modifié pour annuler complètement cette journée, on voit 9H-18H en jaune ? - les annulations ne sont pas affichées ?

Je n'ai pas eu de besoin jusqu'à présent de savoir quelle été la réservation avant la modification de celle-ci.
Cela voudrait dire que l'on aurait une barre jaune (ancien créneau réservé) et la verte (nouveau créneau, actuel).
Dans le cas où je modifie 4 fois mon créneau sur la journée, si on décide d'afficher la barre jaune, ne prendre que le créneau modifié, ceux antérieurs on s'en moque.

Par contre, lorsque l'on avait une réservation qui a été annulée (et non remplacée, c'est à dire pas modifiée, mais bel et bien supprimée) il est important de pouvoir l'afficher (barre jaune) et par la suite les quantifier.
==> ceci sert à pouvoir valoriser le travail effectué (poser une réservation à un moment est du travail, ne plus voir cette résa annulée aurait pour conséquence d'oublier le travaille effectué).

En conclusion, je pense qu'il serait bien d'avoir cette visue en jaune pour les 2 cas, résa modifiée et résa annulée.
En terme de gestion cela peut être intéressant :
"Pourquoi j'ai été facturé 1 heure de plus ?
_ et bien vous étiez réservé de 9h à 18h et non de 8h à 18h..
_ ah non
_ ah si si... vous aviez réservé de 8h à 18h et vous l'avez modifiée de 9h à 18h".

Fin du débat.

Je n'ai pas eu de besoin jusqu'à présent de savoir quelle été la réservation avant la modification de celle-ci. Cela voudrait dire que l'on aurait une barre jaune (ancien créneau réservé) et la verte (nouveau créneau, actuel). Dans le cas où je modifie 4 fois mon créneau sur la journée, si on décide d'afficher la barre jaune, ne prendre que le créneau modifié, ceux antérieurs on s'en moque. Par contre, lorsque l'on avait une réservation qui a été annulée (et non remplacée, c'est à dire pas modifiée, mais bel et bien supprimée) il est important de pouvoir l'afficher (barre jaune) et par la suite les quantifier. ==> ceci sert à pouvoir valoriser le travail effectué (poser une réservation à un moment est du travail, ne plus voir cette résa annulée aurait pour conséquence d'oublier le travaille effectué). En conclusion, je pense qu'il serait bien d'avoir cette visue en jaune pour les 2 cas, résa modifiée et résa annulée. En terme de gestion cela peut être intéressant : "Pourquoi j'ai été facturé 1 heure de plus ? _ et bien vous étiez réservé de 9h à 18h et non de 8h à 18h.. _ ah non _ ah si si... vous aviez réservé de 8h à 18h et vous l'avez modifiée de 9h à 18h". Fin du débat.

Sur jabber j'ai objecté à Cédric que si on ne loggait que la dernière annulation on avait pas de manière fiable de dire « vous aviez réservé de telle heure à telle heure » (il peut y avoir un cycle résa -> modif -> modif avec retour à l'horaire initial qui crée un affichage trompeur).

Le truc qu'on pourrait imaginer c'est une page dédiée à l'historique d'une réservation (petit affichage pour dire « cette résa a été modifiée » et clic dessus et on a toutes les infos).

Mais le plus important c'est que Cédric est d'accord pour avoir ça dans une seconde phase :)

Pas d'affichage des annulations pour le moment, donc.

Je fais un patch qui supprime au lieu d'annuler, ou on le garde comme ça ?

Sur jabber j'ai objecté à Cédric que si on ne loggait que la dernière annulation on avait pas de manière fiable de dire « vous aviez réservé de telle heure à telle heure » (il peut y avoir un cycle résa -> modif -> modif avec retour à l'horaire initial qui crée un affichage trompeur). Le truc qu'on pourrait imaginer c'est une page dédiée à l'historique d'une réservation (petit affichage pour dire « cette résa a été modifiée » et clic dessus et on a toutes les infos). Mais le plus important c'est que Cédric est d'accord pour avoir ça dans une seconde phase :) Pas d'affichage des annulations pour le moment, donc. Je fais un patch qui supprime au lieu d'annuler, ou on le garde comme ça ?

ok pour supprimer au lieu d'annuler

ok pour supprimer au lieu d'annuler

Et j'ai à nouveau embêté Cédric, la conclusion c'est qu'on n'enregistre jamais les réservations annulées lors de la réservation d'une semaine type (même dans le futur, et même en cas de changement de jour).

Et j'ai à nouveau embêté Cédric, la conclusion c'est qu'on n'enregistre jamais les réservations annulées lors de la réservation d'une semaine type (même dans le futur, et même en cas de changement de jour).

on n'enregistre jamais les réservations annulées lors de la réservation d'une semaine type

seulement dans le cas plage libre, ou dans tous les cas ?

> on n'enregistre jamais les réservations annulées lors de la réservation d'une semaine type seulement dans le cas plage libre, ou dans tous les cas ?

vu de vive voix, a priori ça ne concerne que le cas plage libre, à confirmer pour le cas usuel avec stef, cédric et mik (qui utilise cette api pour les seniors (?))

vu de vive voix, a priori ça ne concerne que le cas plage libre, à confirmer pour le cas usuel avec stef, cédric et mik (qui utilise cette api pour les seniors (?))
assert resp.json['cancelled_booking_count'] == 5
assert Booking.objects.count() == 5
assert (
Booking.objects.filter(
cancellation_datetime__isnull=True,
start_time=datetime.time(10, 00),
end_time=datetime.time(15, 00),
event__start_datetime__week_day=4,
).count()
== 5
)