-module(booking_integration_tests). -include_lib("eunit/include/eunit.hrl"). -include("records.hrl"). -define(TABLES, [user, calendar, event, booking]). setup() -> eh_test_support:start_mnesia(), eh_test_support:ensure_tables(?TABLES), ok. cleanup(_) -> eh_test_support:delete_tables(?TABLES), eh_test_support:stop_mnesia(), ok. booking_integration_test_() -> {foreach, fun setup/0, fun cleanup/1, [ {"Booking create stays pending", fun test_pending_booking_flow/0}, {"Full booking flow with manual confirmation", fun test_manual_booking_flow/0}, {"Capacity management test", fun test_capacity_management/0}, {"Multiple bookings test", fun test_multiple_bookings/0} ]}. create_user() -> UserId = base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}), User = #user{ id = UserId, email = <>, password_hash = <<"hash">>, role = user, status = active, created_at = calendar:universal_time(), updated_at = calendar:universal_time() }, mnesia:dirty_write(User), UserId. add_days(DateTime, Days) -> Sec = calendar:datetime_to_gregorian_seconds(DateTime) + Days * 86400, calendar:gregorian_seconds_to_datetime(Sec). test_pending_booking_flow() -> OwnerId = create_user(), ParticipantId = create_user(), {ok, Calendar} = core_calendar:create(OwnerId, <<"Auto">>, <<"">>, auto), StartTime = eh_test_support:future_start(), {ok, Event} = core_event:create(Calendar#calendar.id, <<"Event">>, StartTime, 60), {ok, Booking} = logic_booking:create_booking(ParticipantId, Event#event.id), ?assertEqual(pending, Booking#booking.status), {ok, Stored} = core_booking:get_by_id(Booking#booking.id), ?assertEqual(pending, Stored#booking.status), {ok, EventBookings} = logic_booking:list_event_bookings(Event#event.id), ?assertEqual(1, length(EventBookings)), {ok, UserBookings} = logic_booking:list_user_bookings(ParticipantId), ?assertEqual(1, length(UserBookings)). test_manual_booking_flow() -> OwnerId = create_user(), ParticipantId = create_user(), {ok, Calendar} = core_calendar:create(OwnerId, <<"Manual">>, <<"">>, manual), StartTime = eh_test_support:future_start(), {ok, Event} = core_event:create(Calendar#calendar.id, <<"Event">>, StartTime, 60), {ok, Booking} = logic_booking:create_booking(ParticipantId, Event#event.id), ?assertEqual(pending, Booking#booking.status), {ok, Confirmed} = logic_booking:confirm_booking(OwnerId, Booking#booking.id, confirm), ?assertEqual(confirmed, Confirmed#booking.status), {ok, Cancelled} = logic_booking:cancel_booking(ParticipantId, Booking#booking.id, cancel), ?assertEqual(cancelled, Cancelled#booking.status). test_capacity_management() -> OwnerId = create_user(), Participant1Id = create_user(), Participant2Id = create_user(), Participant3Id = create_user(), {ok, Calendar} = core_calendar:create(OwnerId, <<"Test">>, <<"">>, manual), StartTime = eh_test_support:future_start(), {ok, Event} = core_event:create(Calendar#calendar.id, <<"Event">>, StartTime, 60), {ok, _} = core_event:update(Event#event.id, [{capacity, 2}]), {ok, Booking1} = logic_booking:create_booking(Participant1Id, Event#event.id), {ok, Booking2} = logic_booking:create_booking(Participant2Id, Event#event.id), {ok, _} = logic_booking:confirm_booking(OwnerId, Booking1#booking.id, confirm), {ok, _} = logic_booking:confirm_booking(OwnerId, Booking2#booking.id, confirm), {error, full} = logic_booking:create_booking(Participant3Id, Event#event.id), {ok, _} = logic_booking:cancel_booking(Participant1Id, Booking1#booking.id, cancel), {ok, _} = logic_booking:create_booking(Participant3Id, Event#event.id). test_multiple_bookings() -> OwnerId = create_user(), ParticipantId = create_user(), {ok, Calendar} = core_calendar:create(OwnerId, <<"Test">>, <<"">>, manual), Base = eh_test_support:future_start(), StartTime1 = Base, StartTime2 = add_days(Base, 1), StartTime3 = add_days(Base, 2), {ok, Event1} = core_event:create(Calendar#calendar.id, <<"Event1">>, StartTime1, 60), {ok, Event2} = core_event:create(Calendar#calendar.id, <<"Event2">>, StartTime2, 60), {ok, Event3} = core_event:create(Calendar#calendar.id, <<"Event3">>, StartTime3, 60), {ok, B1} = logic_booking:create_booking(ParticipantId, Event1#event.id), {ok, B2} = logic_booking:create_booking(ParticipantId, Event2#event.id), {ok, _B3} = logic_booking:create_booking(ParticipantId, Event3#event.id), {ok, _} = logic_booking:confirm_booking(OwnerId, B1#booking.id, confirm), {ok, _} = logic_booking:confirm_booking(OwnerId, B2#booking.id, confirm), {ok, UserBookings} = logic_booking:list_user_bookings(ParticipantId), ?assertEqual(3, length(UserBookings)), ConfirmedCount = length([B || B <- UserBookings, B#booking.status =:= confirmed]), ?assertEqual(2, ConfirmedCount), PendingCount = length([B || B <- UserBookings, B#booking.status =:= pending]), ?assertEqual(1, PendingCount).