plages libres, permettre la mise à jour des plages d'une semaine type #78084 #101
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
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)
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):
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 ?
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).
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 (?))