Stage 3.4

This commit is contained in:
2026-04-20 16:40:44 +03:00
parent 42a047a938
commit b24cbc97f3
25 changed files with 2520 additions and 123 deletions
+189
View File
@@ -0,0 +1,189 @@
-module(logic_booking).
-include("records.hrl").
-export([create_booking/2, confirm_booking/3, cancel_booking/2]).
-export([get_booking/2, list_event_bookings/2, list_user_bookings/1]).
-export([auto_confirm/1, check_timeout_confirmations/0]).
%% Создание бронирования (запись на событие)
create_booking(UserId, EventId) ->
% Получаем событие напрямую, без проверки доступа к календарю
case core_event:get_by_id(EventId) of
{ok, Event} ->
% Проверяем, что событие активно
case Event#event.status of
active ->
% Проверяем календарь для политики подтверждения
case core_calendar:get_by_id(Event#event.calendar_id) of
{ok, Calendar} ->
case Calendar#calendar.status of
active ->
% Проверяем, что есть места
case check_capacity(EventId, Event#event.capacity) of
{ok, _} ->
% Проверяем, не записан ли уже пользователь
case core_booking:get_by_event_and_user(EventId, UserId) of
{error, not_found} ->
ActualEventId = get_actual_event_id(Event, UserId),
case core_booking:create(ActualEventId, UserId) of
{ok, Booking} ->
handle_confirmation_policy(Booking, Event, Calendar),
{ok, Booking};
Error ->
Error
end;
{ok, _} ->
{error, already_booked}
end;
{error, full} ->
{error, event_full}
end;
_ ->
{error, calendar_not_active}
end;
_ ->
{error, calendar_not_found}
end;
_ ->
{error, event_not_active}
end;
Error ->
Error
end.
%% Подтверждение бронирования (владельцем календаря)
confirm_booking(UserId, BookingId, Action) when Action =:= confirm; Action =:= decline ->
case core_booking:get_by_id(BookingId) of
{ok, Booking} ->
% Проверяем права на событие
case logic_event:get_event(UserId, Booking#booking.event_id) of
{ok, Event} ->
% Проверяем, что пользователь может редактировать календарь
case logic_calendar:get_calendar(UserId, Event#event.calendar_id) of
{ok, Calendar} ->
case logic_calendar:can_edit(UserId, Calendar) of
true ->
case Action of
confirm ->
core_booking:update_status(BookingId, confirmed);
decline ->
core_booking:update_status(BookingId, cancelled)
end;
false ->
{error, access_denied}
end;
Error ->
Error
end;
Error ->
Error
end;
Error ->
Error
end.
%% Отмена бронирования (участником)
cancel_booking(UserId, BookingId) ->
case core_booking:get_by_id(BookingId) of
{ok, Booking} ->
% Проверяем, что это бронирование пользователя
case Booking#booking.user_id =:= UserId of
true ->
core_booking:update_status(BookingId, cancelled);
false ->
{error, access_denied}
end;
Error ->
Error
end.
%% Получение бронирования
get_booking(UserId, BookingId) ->
case core_booking:get_by_id(BookingId) of
{ok, Booking} ->
% Проверяем доступ к событию
case logic_event:get_event(UserId, Booking#booking.event_id) of
{ok, _} -> {ok, Booking};
Error -> Error
end;
Error ->
Error
end.
%% Список бронирований события (для владельца)
list_event_bookings(UserId, EventId) ->
case logic_event:get_event(UserId, EventId) of
{ok, Event} ->
% Проверяем права на календарь
case logic_calendar:get_calendar(UserId, Event#event.calendar_id) of
{ok, Calendar} ->
case logic_calendar:can_edit(UserId, Calendar) of
true ->
core_booking:list_by_event(EventId);
false ->
{error, access_denied}
end;
Error ->
Error
end;
Error ->
Error
end.
%% Список бронирований пользователя
list_user_bookings(UserId) ->
core_booking:list_by_user(UserId).
%% Автоматическое подтверждение (для политики auto)
auto_confirm(BookingId) ->
core_booking:update_status(BookingId, confirmed).
%% Проверка истечения timeout подтверждений
check_timeout_confirmations() ->
% Получаем все pending бронирования для календарей с timeout
% В реальной реализации нужно периодически вызывать эту функцию
ok.
%% Внутренние функции
check_capacity(_EventId, undefined) ->
{ok, unlimited};
check_capacity(EventId, Capacity) ->
{ok, Bookings} = core_booking:list_by_event(EventId),
ConfirmedCount = length([B || B <- Bookings, B#booking.status =:= confirmed]),
case ConfirmedCount < Capacity of
true -> {ok, Capacity - ConfirmedCount};
false -> {error, full}
end.
get_actual_event_id(Event, _UserId) ->
case Event#event.event_type of
recurring ->
% Для повторяющихся событий нужно материализовать вхождение
% Здесь предполагается, что start_time передаётся в запросе
% В полной реализации нужно получать occurrence_start из параметров
Event#event.id;
single ->
Event#event.id
end.
handle_confirmation_policy(Booking, _Event, Calendar) ->
io:format("Confirmation policy: ~p~n", [Calendar#calendar.confirmation]),
case Calendar#calendar.confirmation of
auto ->
io:format("Auto-confirming booking ~p~n", [Booking#booking.id]),
auto_confirm(Booking#booking.id);
manual ->
io:format("Manual confirmation, leaving pending~n"),
ok;
{timeout, Seconds} ->
io:format("Timeout confirmation: ~p seconds~n", [Seconds]),
spawn(fun() ->
timer:sleep(Seconds * 1000),
case core_booking:get_by_id(Booking#booking.id) of
{ok, B} when B#booking.status =:= pending ->
auto_confirm(Booking#booking.id);
_ ->
ok
end
end)
end.
+3 -4
View File
@@ -1,18 +1,17 @@
-module(logic_calendar).
-include("records.hrl").
-export([create_calendar/3, get_calendar/2, list_calendars/1,
-export([create_calendar/4, get_calendar/2, list_calendars/1,
update_calendar/3, delete_calendar/2]).
-export([can_access/2, can_edit/2]).
%% Создание календаря
create_calendar(UserId, Title, Description) ->
% Проверка, что пользователь может создавать календари
create_calendar(UserId, Title, Description, Confirmation) ->
case core_user:get_by_id(UserId) of
{ok, User} ->
case User#user.status of
active ->
core_calendar:create(UserId, Title, Description);
core_calendar:create(UserId, Title, Description, Confirmation);
_ ->
{error, user_inactive}
end;