feat(booking): materialize occurrence on POST bookings. Refs EventHub/EventHubBack#67

This commit is contained in:
2026-08-14 10:52:24 +03:00
parent e3403f6ed6
commit 8a5f254c2a
5 changed files with 220 additions and 35 deletions
+58 -1
View File
@@ -2,7 +2,8 @@
-include_lib("eunit/include/eunit.hrl").
-include("records.hrl").
-define(TABLES, [user, calendar, event, booking, admin, subscription, calendar_specialist]).
-define(TABLES, [user, calendar, event, booking, admin, subscription, calendar_specialist,
recurrence_exception]).
setup() ->
eh_test_support:start_mnesia(),
@@ -21,6 +22,10 @@ logic_booking_test_() ->
[
{"Create booking auto confirms", fun test_create_booking_auto/0},
{"Create booking manual pending", fun test_create_booking_pending/0},
{"Recurring booking requires occurrence_start", fun test_recurring_requires_occurrence/0},
{"Recurring booking materializes occurrence", fun test_recurring_books_occurrence/0},
{"Recurring booking rejects invalid occurrence", fun test_recurring_invalid_occurrence/0},
{"Recurring booking rejects cancelled occurrence", fun test_recurring_cancelled_occurrence/0},
{"Create booking personal denied", fun test_booking_personal_denied/0},
{"Create duplicate booking", fun test_create_duplicate_booking/0},
{"Create booking for missing event", fun test_booking_missing_event/0},
@@ -96,6 +101,16 @@ past_start() ->
Sec = calendar:datetime_to_gregorian_seconds(calendar:universal_time()) - 3600,
calendar:gregorian_seconds_to_datetime(Sec).
add_days(DateTime, Days) ->
Sec = calendar:datetime_to_gregorian_seconds(DateTime) + Days * 86400,
calendar:gregorian_seconds_to_datetime(Sec).
create_recurring_event(CalendarId) ->
StartTime = eh_test_support:future_start(),
RRule = #{<<"freq">> => <<"WEEKLY">>, <<"interval">> => 1},
{ok, Event} = core_event:create_recurring(CalendarId, <<"Series">>, StartTime, 60, RRule),
{Event#event.id, StartTime}.
create_test_event_with_capacity(CalendarId, Capacity) ->
StartTime = eh_test_support:future_start(),
{ok, Event} = core_event:create(CalendarId, <<"Test Event">>, StartTime, 60),
@@ -124,6 +139,48 @@ test_create_booking_pending() ->
{ok, Stored} = core_booking:get_by_id(Booking#booking.id),
?assertEqual(pending, Stored#booking.status).
test_recurring_requires_occurrence() ->
OwnerId = create_test_user(user),
ParticipantId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, auto),
{MasterId, _} = create_recurring_event(CalendarId),
{error, occurrence_start_required} = logic_booking:create_booking(ParticipantId, MasterId).
test_recurring_books_occurrence() ->
OwnerId = create_test_user(user),
ParticipantId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, auto),
{MasterId, StartTime} = create_recurring_event(CalendarId),
Occ = add_days(StartTime, 7),
{ok, Booking} = logic_booking:create_booking(ParticipantId, MasterId, Occ),
{ok, BookedEvent} = core_event:get_by_id(Booking#booking.event_id),
?assertEqual(true, BookedEvent#event.is_instance),
?assertEqual(MasterId, BookedEvent#event.master_id),
?assertEqual(Occ, BookedEvent#event.start_time),
?assertNotEqual(MasterId, Booking#booking.event_id).
test_recurring_invalid_occurrence() ->
OwnerId = create_test_user(user),
ParticipantId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, auto),
{MasterId, StartTime} = create_recurring_event(CalendarId),
Bad = add_days(StartTime, 1),
{error, invalid_occurrence} = logic_booking:create_booking(ParticipantId, MasterId, Bad).
test_recurring_cancelled_occurrence() ->
OwnerId = create_test_user(user),
ParticipantId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, auto),
{MasterId, StartTime} = create_recurring_event(CalendarId),
Occ = add_days(StartTime, 7),
mnesia:dirty_write(#recurrence_exception{
master_id = MasterId,
original_start = Occ,
action = cancel,
new_start = undefined
}),
{error, invalid_occurrence} = logic_booking:create_booking(ParticipantId, MasterId, Occ).
test_booking_personal_denied() ->
OwnerId = create_test_user(user),
ParticipantId = create_test_user(user),