0002-api-use-custody-agendas-date-start-66330.patch
chrono/agendas/models.py | ||
---|---|---|
837 | 837 | |
838 | 838 |
@staticmethod |
839 | 839 |
def filter_for_guardian(qs, guardian_external_id, child_external_id): |
840 |
agendas = SharedCustodyAgenda.objects.filter(children__user_external_id=child_external_id) |
|
840 | 841 |
qs = ( |
841 | 842 |
qs.annotate(week=ExtractWeek('start_datetime')) |
842 | 843 |
.annotate(week_number=Cast('week', models.IntegerField())) |
843 | 844 |
.annotate(odd_week=F('week_number') % 2) |
844 | 845 |
) |
846 | ||
847 |
previous_date_start = None |
|
848 |
filtered_qs = Event.objects.none() |
|
849 |
for agenda in agendas.order_by('-date_start'): |
|
850 |
filtered_qs |= Agenda.filter_for_custody_agenda( |
|
851 |
qs, agenda, guardian_external_id, date_end=previous_date_start |
|
852 |
) |
|
853 |
previous_date_start = agenda.date_start |
|
854 | ||
855 |
return filtered_qs |
|
856 | ||
857 |
@staticmethod |
|
858 |
def filter_for_custody_agenda(qs, agenda, guardian_external_id, date_end=None): |
|
845 | 859 |
rules = ( |
846 | 860 |
SharedCustodyRule.objects.filter( |
847 | 861 |
guardian__user_external_id=guardian_external_id, |
848 |
agenda__children__user_external_id=child_external_id,
|
|
862 |
agenda=agenda,
|
|
849 | 863 |
) |
850 | 864 |
.annotate(day=Func(F('days'), function='unnest')) |
851 | 865 |
.annotate(week_day=(F('day') + 1) % 7 + 1) # convert ISO day number to db lookup day number |
... | ... | |
859 | 873 |
) |
860 | 874 | |
861 | 875 |
all_periods = SharedCustodyPeriod.objects.filter( |
862 |
agenda__children__user_external_id=child_external_id,
|
|
876 |
agenda=agenda,
|
|
863 | 877 |
date_start__lte=OuterRef('start_datetime'), |
864 | 878 |
date_end__gt=OuterRef('start_datetime'), |
865 | 879 |
) |
... | ... | |
879 | 893 |
) |
880 | 894 | |
881 | 895 |
rules_lookup = (rules_lookup | Q(in_holiday_period=True)) & Q(in_excluded_holiday_period=False) |
882 |
return qs.filter( |
|
883 |
(rules_lookup | Q(in_exceptional_period=True)) & Q(in_excluded_exceptional_period=False) |
|
896 |
qs = qs.filter( |
|
897 |
(rules_lookup | Q(in_exceptional_period=True)) & Q(in_excluded_exceptional_period=False), |
|
898 |
start_datetime__gte=agenda.date_start, |
|
884 | 899 |
) |
900 |
if date_end: |
|
901 |
qs = qs.filter(start_datetime__lt=date_end) |
|
902 | ||
903 |
return qs |
|
885 | 904 | |
886 | 905 |
@staticmethod |
887 | 906 |
def prefetch_recurring_events(qs, with_overlaps=False): |
tests/api/datetimes/test_events_multiple_agendas.py | ||
---|---|---|
420 | 420 |
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe') |
421 | 421 |
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe') |
422 | 422 |
child = Person.objects.create(user_external_id='xxx', first_name='James', last_name='Doe') |
423 |
agenda = SharedCustodyAgenda.objects.create( |
|
424 |
first_guardian=father, second_guardian=mother, date_start=now() - datetime.timedelta(days=5) |
|
425 |
) |
|
426 |
agenda.children.add(child) |
|
423 |
for i in range(5): |
|
424 |
agenda = SharedCustodyAgenda.objects.create( |
|
425 |
first_guardian=father, second_guardian=mother, date_start=now() - datetime.timedelta(days=5 + i) |
|
426 |
) |
|
427 |
agenda.children.add(child) |
|
427 | 428 | |
428 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)), weeks='even') |
|
429 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='odd') |
|
429 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)), weeks='even')
|
|
430 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='odd')
|
|
430 | 431 | |
431 | 432 |
with CaptureQueriesContext(connection) as ctx: |
432 | 433 |
resp = app.get( |
... | ... | |
440 | 441 |
}, |
441 | 442 |
) |
442 | 443 |
assert len(resp.json['data']) == 30 |
443 |
assert len(ctx.captured_queries) == 2
|
|
444 |
assert len(ctx.captured_queries) == 3
|
|
444 | 445 | |
445 | 446 | |
446 | 447 |
@pytest.mark.freeze_time('2021-05-06 14:00') |
... | ... | |
1216 | 1217 |
assert len(resp.json['data']) == 1 |
1217 | 1218 | |
1218 | 1219 | |
1220 |
@pytest.mark.freeze_time('2022-03-07 14:00') # Monday of 10th week |
|
1221 |
def test_datetimes_multiple_agendas_shared_custody_date_start(app): |
|
1222 |
agenda = Agenda.objects.create(label='First agenda', kind='events') |
|
1223 |
Desk.objects.create(agenda=agenda, slug='_exceptions_holder') |
|
1224 |
start_datetime = make_aware(datetime.datetime(year=2022, month=3, day=9, hour=14, minute=0)) |
|
1225 |
wednesday_event = Event.objects.create( |
|
1226 |
slug='event-wednesday', |
|
1227 |
start_datetime=start_datetime, |
|
1228 |
recurrence_days=[2], |
|
1229 |
recurrence_end_date=start_datetime + datetime.timedelta(days=30), |
|
1230 |
places=5, |
|
1231 |
agenda=agenda, |
|
1232 |
) |
|
1233 |
wednesday_event.create_all_recurrences() |
|
1234 |
Subscription.objects.create( |
|
1235 |
agenda=agenda, |
|
1236 |
user_external_id='child_id', |
|
1237 |
date_start=now(), |
|
1238 |
date_end=now() + datetime.timedelta(days=30), |
|
1239 |
) |
|
1240 | ||
1241 |
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe') |
|
1242 |
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe') |
|
1243 |
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe') |
|
1244 |
agenda = SharedCustodyAgenda.objects.create( |
|
1245 |
first_guardian=father, second_guardian=mother, date_start=now() |
|
1246 |
) |
|
1247 |
agenda.children.add(child) |
|
1248 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7))) |
|
1249 | ||
1250 |
resp = app.get( |
|
1251 |
'/api/agendas/datetimes/', |
|
1252 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, |
|
1253 |
) |
|
1254 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1255 |
'first-agenda@event-wednesday--2022-03-09-1400', |
|
1256 |
'first-agenda@event-wednesday--2022-03-16-1400', |
|
1257 |
'first-agenda@event-wednesday--2022-03-23-1400', |
|
1258 |
'first-agenda@event-wednesday--2022-03-30-1400', |
|
1259 |
] |
|
1260 | ||
1261 |
resp = app.get( |
|
1262 |
'/api/agendas/datetimes/', |
|
1263 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, |
|
1264 |
) |
|
1265 |
assert len(resp.json['data']) == 0 |
|
1266 | ||
1267 |
agenda = SharedCustodyAgenda.objects.create( |
|
1268 |
first_guardian=father, second_guardian=mother, date_start=datetime.date(year=2022, month=3, day=10) |
|
1269 |
) |
|
1270 |
agenda.children.add(child) |
|
1271 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7))) |
|
1272 | ||
1273 |
resp = app.get( |
|
1274 |
'/api/agendas/datetimes/', |
|
1275 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, |
|
1276 |
) |
|
1277 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1278 |
'first-agenda@event-wednesday--2022-03-09-1400', |
|
1279 |
] |
|
1280 | ||
1281 |
resp = app.get( |
|
1282 |
'/api/agendas/datetimes/', |
|
1283 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, |
|
1284 |
) |
|
1285 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1286 |
'first-agenda@event-wednesday--2022-03-16-1400', |
|
1287 |
'first-agenda@event-wednesday--2022-03-23-1400', |
|
1288 |
'first-agenda@event-wednesday--2022-03-30-1400', |
|
1289 |
] |
|
1290 | ||
1291 |
agenda = SharedCustodyAgenda.objects.create( |
|
1292 |
first_guardian=father, second_guardian=mother, date_start=datetime.date(year=2022, month=3, day=17) |
|
1293 |
) |
|
1294 |
agenda.children.add(child) |
|
1295 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)), weeks='odd') |
|
1296 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='even') |
|
1297 | ||
1298 |
resp = app.get( |
|
1299 |
'/api/agendas/datetimes/', |
|
1300 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, |
|
1301 |
) |
|
1302 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1303 |
'first-agenda@event-wednesday--2022-03-09-1400', |
|
1304 |
'first-agenda@event-wednesday--2022-03-30-1400', |
|
1305 |
] |
|
1306 | ||
1307 |
resp = app.get( |
|
1308 |
'/api/agendas/datetimes/', |
|
1309 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, |
|
1310 |
) |
|
1311 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1312 |
'first-agenda@event-wednesday--2022-03-16-1400', |
|
1313 |
'first-agenda@event-wednesday--2022-03-23-1400', |
|
1314 |
] |
|
1315 | ||
1316 |
other_person = Person.objects.create(user_external_id='other_person', first_name='O', last_name='P') |
|
1317 |
agenda = SharedCustodyAgenda.objects.create( |
|
1318 |
first_guardian=other_person, |
|
1319 |
second_guardian=mother, |
|
1320 |
date_start=datetime.date(year=2022, month=3, day=22), |
|
1321 |
) |
|
1322 |
agenda.children.add(child) |
|
1323 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=other_person, days=list(range(7)), weeks='odd') |
|
1324 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='even') |
|
1325 | ||
1326 |
resp = app.get( |
|
1327 |
'/api/agendas/datetimes/', |
|
1328 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, |
|
1329 |
) |
|
1330 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1331 |
'first-agenda@event-wednesday--2022-03-09-1400', |
|
1332 |
] |
|
1333 | ||
1334 |
resp = app.get( |
|
1335 |
'/api/agendas/datetimes/', |
|
1336 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'other_person'}, |
|
1337 |
) |
|
1338 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1339 |
'first-agenda@event-wednesday--2022-03-30-1400', |
|
1340 |
] |
|
1341 | ||
1342 |
resp = app.get( |
|
1343 |
'/api/agendas/datetimes/', |
|
1344 |
params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, |
|
1345 |
) |
|
1346 |
assert [d['id'] for d in resp.json['data']] == [ |
|
1347 |
'first-agenda@event-wednesday--2022-03-16-1400', |
|
1348 |
'first-agenda@event-wednesday--2022-03-23-1400', |
|
1349 |
] |
|
1350 | ||
1351 | ||
1219 | 1352 |
def test_datetimes_multiple_agendas_with_status(app): |
1220 | 1353 |
group = CheckTypeGroup.objects.create(label='Foo bar') |
1221 | 1354 |
check_type_absence = CheckType.objects.create(label='Foo reason', group=group, kind='absence') |
tests/api/datetimes/test_recurring_events.py | ||
---|---|---|
253 | 253 |
assert [x['id'] for x in resp.json['data']] == ['foo-bar@event:0', 'foo-bar@event:1', 'foo-bar@event:2'] |
254 | 254 | |
255 | 255 | |
256 |
@pytest.mark.freeze_time('2021-12-13 14:00') # Monday of 50th week |
|
257 |
def test_recurring_events_api_list_shared_custody_start_date(app): |
|
258 |
agenda = Agenda.objects.create( |
|
259 |
label='Foo bar', kind='events', minimal_booking_delay=1, maximal_booking_delay=30 |
|
260 |
) |
|
261 |
Desk.objects.create(agenda=agenda, slug='_exceptions_holder') |
|
262 |
event = Event.objects.create( |
|
263 |
slug='event', |
|
264 |
start_datetime=now(), |
|
265 |
recurrence_days=[0, 1, 2], |
|
266 |
recurrence_end_date=now() + datetime.timedelta(days=30), |
|
267 |
places=5, |
|
268 |
agenda=agenda, |
|
269 |
) |
|
270 |
event.create_all_recurrences() |
|
271 | ||
272 |
resp = app.get('/api/agendas/recurring-events/', params={'agendas': agenda.slug}) |
|
273 |
assert [x['id'] for x in resp.json['data']] == ['foo-bar@event:0', 'foo-bar@event:1', 'foo-bar@event:2'] |
|
274 | ||
275 |
# add shared two custody agendas |
|
276 |
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe') |
|
277 |
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe') |
|
278 |
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe') |
|
279 | ||
280 |
custody_agenda = SharedCustodyAgenda.objects.create( |
|
281 |
first_guardian=father, second_guardian=mother, date_start=now() |
|
282 |
) |
|
283 |
custody_agenda.children.add(child) |
|
284 |
SharedCustodyRule.objects.create(agenda=custody_agenda, guardian=father, days=[0], weeks='even') |
|
285 |
SharedCustodyRule.objects.create(agenda=custody_agenda, guardian=mother, days=[1, 2], weeks='odd') |
|
286 | ||
287 |
custody_agenda2 = SharedCustodyAgenda.objects.create( |
|
288 |
first_guardian=father, second_guardian=mother, date_start=now() + datetime.timedelta(days=15) |
|
289 |
) |
|
290 |
custody_agenda2.children.add(child) |
|
291 |
SharedCustodyRule.objects.create(agenda=custody_agenda2, guardian=father, days=[1], weeks='even') |
|
292 |
SharedCustodyRule.objects.create(agenda=custody_agenda2, guardian=mother, days=[0, 2], weeks='odd') |
|
293 | ||
294 |
resp = app.get( |
|
295 |
'/api/agendas/recurring-events/', |
|
296 |
params={'agendas': agenda.slug, 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, |
|
297 |
) |
|
298 |
assert [x['id'] for x in resp.json['data']] == ['foo-bar@event:0', 'foo-bar@event:1'] |
|
299 | ||
300 |
resp = app.get( |
|
301 |
'/api/agendas/recurring-events/', |
|
302 |
params={'agendas': agenda.slug, 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, |
|
303 |
) |
|
304 |
assert [x['id'] for x in resp.json['data']] == ['foo-bar@event:0', 'foo-bar@event:1', 'foo-bar@event:2'] |
|
305 | ||
306 | ||
256 | 307 |
@pytest.mark.freeze_time('2021-09-06 12:00') |
257 | 308 |
def test_recurring_events_api_list_multiple_agendas(app): |
258 | 309 |
agenda = Agenda.objects.create(label='First Agenda', kind='events') |
... | ... | |
345 | 396 |
'/api/agendas/recurring-events/?subscribed=category-a&user_external_id=xxx&guardian_external_id=father_id' |
346 | 397 |
) |
347 | 398 |
assert len(resp.json['data']) == 40 |
348 |
assert len(ctx.captured_queries) == 4
|
|
399 |
assert len(ctx.captured_queries) == 5
|
|
349 | 400 | |
350 | 401 | |
351 | 402 |
@pytest.mark.freeze_time('2021-09-06 12:00') |
tests/api/fillslot/test_events_multiple_agendas.py | ||
---|---|---|
652 | 652 |
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-thursday' |
653 | 653 | |
654 | 654 | |
655 |
@pytest.mark.freeze_time('2022-03-07 14:00') # Monday of 10th week |
|
656 |
def test_api_events_fillslots_multiple_agendas_shared_custody_date_start(app, user): |
|
657 |
agenda = Agenda.objects.create(label='First agenda', kind='events') |
|
658 |
Desk.objects.create(agenda=agenda, slug='_exceptions_holder') |
|
659 |
Event.objects.create( |
|
660 |
slug='event-wednesday', |
|
661 |
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=9, hour=14, minute=0)), |
|
662 |
places=5, |
|
663 |
agenda=agenda, |
|
664 |
) |
|
665 |
Event.objects.create( |
|
666 |
slug='event-thursday', |
|
667 |
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=10, hour=14, minute=0)), |
|
668 |
places=5, |
|
669 |
agenda=agenda, |
|
670 |
) |
|
671 |
Subscription.objects.create( |
|
672 |
agenda=agenda, |
|
673 |
user_external_id='child_id', |
|
674 |
date_start=now(), |
|
675 |
date_end=now() + datetime.timedelta(days=14), |
|
676 |
) |
|
677 | ||
678 |
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe') |
|
679 |
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe') |
|
680 |
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe') |
|
681 | ||
682 |
agenda = SharedCustodyAgenda.objects.create( |
|
683 |
first_guardian=father, second_guardian=mother, date_start=now() |
|
684 |
) |
|
685 |
agenda.children.add(child) |
|
686 |
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7))) |
|
687 | ||
688 |
agenda2 = SharedCustodyAgenda.objects.create( |
|
689 |
first_guardian=father, second_guardian=mother, date_start=datetime.date(year=2022, month=3, day=10) |
|
690 |
) |
|
691 |
agenda2.children.add(child) |
|
692 |
SharedCustodyRule.objects.create(agenda=agenda2, guardian=mother, days=list(range(7))) |
|
693 | ||
694 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
695 |
params = {'user_external_id': 'child_id', 'slots': 'first-agenda@event-wednesday'} |
|
696 |
resp = app.post_json( |
|
697 |
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=father_id', params=params |
|
698 |
) |
|
699 |
assert resp.json['booking_count'] == 1 |
|
700 | ||
701 |
resp = app.post_json( |
|
702 |
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id', |
|
703 |
params=params, |
|
704 |
status=400, |
|
705 |
) |
|
706 |
assert resp.json['err'] == 1 |
|
707 |
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-wednesday' |
|
708 | ||
709 |
params['slots'] = 'first-agenda@event-thursday' |
|
710 |
resp = app.post_json( |
|
711 |
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id', params=params |
|
712 |
) |
|
713 |
assert resp.json['booking_count'] == 1 |
|
714 | ||
715 |
params['slots'] = 'first-agenda@event-thursday' |
|
716 |
resp = app.post_json( |
|
717 |
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=father_id', |
|
718 |
params=params, |
|
719 |
status=400, |
|
720 |
) |
|
721 |
assert resp.json['err'] == 1 |
|
722 |
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-thursday' |
|
723 | ||
724 | ||
655 | 725 |
@pytest.mark.freeze_time('2021-09-06 12:00') |
656 | 726 |
def test_api_events_fillslots_multiple_agendas_overlapping_events(app, user, freezer): |
657 | 727 |
agenda = Agenda.objects.create(label='Foo bar', kind='events') |
tests/api/fillslot/test_recurring_events.py | ||
---|---|---|
1312 | 1312 |
params={'slots': events_to_book, 'user_external_id': 'xxx'}, |
1313 | 1313 |
) |
1314 | 1314 |
assert resp.json['booking_count'] == 100 |
1315 |
assert len(ctx.captured_queries) == 13
|
|
1315 |
assert len(ctx.captured_queries) == 14
|
|
1316 | 1316 | |
1317 | 1317 | |
1318 | 1318 |
@pytest.mark.freeze_time('2022-03-07 14:00') # Monday of 10th week |
... | ... | |
1377 | 1377 |
'2022-03-20', |
1378 | 1378 |
] |
1379 | 1379 | |
1380 |
# give father full custody from 14/03/2022 |
|
1381 |
agenda2 = SharedCustodyAgenda.objects.create( |
|
1382 |
first_guardian=father, second_guardian=mother, date_start=datetime.date(year=2022, month=3, day=14) |
|
1383 |
) |
|
1384 |
agenda2.children.add(child) |
|
1385 | ||
1386 |
SharedCustodyRule.objects.create(agenda=agenda2, guardian=father, days=list(range(7))) |
|
1387 |
Booking.objects.all().delete() |
|
1388 | ||
1389 |
resp = app.post_json(fillslots_url % 'father_id', params=params) |
|
1390 |
assert [x['date'] for x in resp.json['booked_events']] == [ |
|
1391 |
'2022-03-10', |
|
1392 |
'2022-03-11', |
|
1393 |
'2022-03-12', |
|
1394 |
'2022-03-14', |
|
1395 |
'2022-03-15', |
|
1396 |
'2022-03-16', |
|
1397 |
'2022-03-17', |
|
1398 |
'2022-03-18', |
|
1399 |
'2022-03-19', |
|
1400 |
'2022-03-20', |
|
1401 |
] |
|
1402 | ||
1403 |
resp = app.post_json(fillslots_url % 'mother_id', params=params) |
|
1404 |
assert [x['date'] for x in resp.json['booked_events']] == [ |
|
1405 |
'2022-03-07', |
|
1406 |
'2022-03-08', |
|
1407 |
'2022-03-09', |
|
1408 |
'2022-03-13', # last date before new agenda rules apply |
|
1409 |
] |
|
1410 | ||
1380 | 1411 | |
1381 | 1412 |
@pytest.mark.freeze_time('2021-09-06 12:00') |
1382 | 1413 |
def test_recurring_events_api_fillslots_overlapping_events(app, user): |
1383 |
- |