-module(booking_integration_tests). -include_lib("eunit/include/eunit.hrl"). -include("records.hrl"). setup() -> mnesia:start(), mnesia:create_table(user, [ {attributes, record_info(fields, user)}, {ram_copies, [node()]} ]), mnesia:create_table(calendar, [ {attributes, record_info(fields, calendar)}, {ram_copies, [node()]} ]), mnesia:create_table(event, [ {attributes, record_info(fields, event)}, {ram_copies, [node()]} ]), mnesia:create_table(booking, [ {attributes, record_info(fields, booking)}, {ram_copies, [node()]} ]), ok. cleanup(_) -> mnesia:delete_table(booking), mnesia:delete_table(event), mnesia:delete_table(calendar), mnesia:delete_table(user), mnesia:stop(), ok. booking_integration_test_() -> {foreach, fun setup/0, fun cleanup/1, [ {"Full booking flow with auto confirmation", fun test_auto_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. test_auto_booking_flow() -> OwnerId = create_user(), ParticipantId = create_user(), {ok, Calendar} = core_calendar:create(OwnerId, <<"Auto">>, <<"">>, auto), StartTime = {{2026, 6, 1}, {10, 0, 0}}, {ok, Event} = core_event:create(Calendar#calendar.id, <<"Event">>, StartTime, 60), {ok, Booking} = logic_booking:create_booking(ParticipantId, Event#event.id), timer:sleep(100), {ok, Updated} = core_booking:get_by_id(Booking#booking.id), ?assertEqual(confirmed, Updated#booking.status), {ok, EventBookings} = logic_booking:list_event_bookings(OwnerId, 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 = {{2026, 6, 1}, {10, 0, 0}}, {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), ?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">>, <<"">>, auto), StartTime = {{2026, 6, 1}, {10, 0, 0}}, {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), {error, event_full} = logic_booking:create_booking(Participant3Id, Event#event.id), % Участник 1 отменяет своё бронирование {ok, _} = logic_booking:cancel_booking(Participant1Id, Booking1#booking.id), % Теперь третий может записаться {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), StartTime1 = {{2026, 6, 1}, {10, 0, 0}}, StartTime2 = {{2026, 6, 2}, {10, 0, 0}}, StartTime3 = {{2026, 6, 3}, {10, 0, 0}}, {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).