165 lines
5.9 KiB
Erlang
165 lines
5.9 KiB
Erlang
-module(logic_calendar).
|
|
-include("records.hrl").
|
|
|
|
-export([create_calendar/3, create_calendar/4, get_calendar/2, list_calendars/1,
|
|
update_calendar/3, delete_calendar/2]).
|
|
-export([can_access/2, can_edit/2]).
|
|
-export([admin_list_all/0, admin_get_by_id/1, admin_update/2, admin_delete/1]).
|
|
|
|
%% Создание календаря с политикой по умолчанию (manual)
|
|
create_calendar(UserId, Title, Description) ->
|
|
create_calendar(UserId, Title, Description, manual).
|
|
|
|
%% Создание календаря с указанной политикой подтверждения
|
|
create_calendar(UserId, Title, Description, Confirmation) ->
|
|
Type = personal, % По умолчанию
|
|
create_calendar(UserId, Title, Description, Confirmation, Type).
|
|
|
|
create_calendar(UserId, Title, Description, Confirmation, Type) ->
|
|
case core_user:get_by_id(UserId) of
|
|
{ok, User} ->
|
|
case User#user.status of
|
|
active ->
|
|
case Type of
|
|
commercial ->
|
|
case logic_subscription:can_create_commercial_calendar(UserId) of
|
|
true ->
|
|
core_calendar:create(UserId, Title, Description, Confirmation, Type);
|
|
false ->
|
|
{error, subscription_required}
|
|
end;
|
|
personal ->
|
|
core_calendar:create(UserId, Title, Description, Confirmation, Type)
|
|
end;
|
|
_ ->
|
|
{error, user_inactive}
|
|
end;
|
|
{error, _} ->
|
|
{error, user_not_found}
|
|
end.
|
|
|
|
%% Получение календаря с проверкой доступа
|
|
get_calendar(UserId, CalendarId) ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, Calendar} ->
|
|
case can_access(UserId, Calendar) of
|
|
true -> {ok, Calendar};
|
|
false -> {error, access_denied}
|
|
end;
|
|
Error ->
|
|
Error
|
|
end.
|
|
|
|
%% Список календарей пользователя
|
|
list_calendars(UserId) ->
|
|
core_calendar:list_by_owner(UserId).
|
|
|
|
%% Обновление календаря
|
|
update_calendar(UserId, CalendarId, Updates) ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, Calendar} ->
|
|
case can_edit(UserId, Calendar) of
|
|
true ->
|
|
ValidUpdates = validate_updates(Updates),
|
|
core_calendar:update(CalendarId, ValidUpdates);
|
|
false ->
|
|
{error, access_denied}
|
|
end;
|
|
Error ->
|
|
Error
|
|
end.
|
|
|
|
%% Удаление календаря
|
|
delete_calendar(UserId, CalendarId) ->
|
|
case core_calendar:get_by_id(CalendarId) of
|
|
{ok, Calendar} ->
|
|
case can_edit(UserId, Calendar) of
|
|
true ->
|
|
core_calendar:delete(CalendarId);
|
|
false ->
|
|
{error, access_denied}
|
|
end;
|
|
Error ->
|
|
Error
|
|
end.
|
|
|
|
%% Проверка прав доступа (просмотр)
|
|
can_access(UserId, #calendar{owner_id = UserId, status = active}) ->
|
|
true;
|
|
can_access(_UserId, #calendar{type = commercial, status = active}) ->
|
|
true;
|
|
can_access(_UserId, _) ->
|
|
false.
|
|
|
|
%% Проверка прав редактирования
|
|
can_edit(UserId, #calendar{owner_id = UserId, status = active}) ->
|
|
true;
|
|
can_edit(_UserId, #calendar{owner_id = _OwnerId}) ->
|
|
false;
|
|
can_edit(_, _) ->
|
|
false.
|
|
|
|
%% Валидация полей обновления
|
|
validate_updates(Updates) ->
|
|
lists:filter(fun validate_update/1, Updates).
|
|
|
|
validate_update({title, Value}) when is_binary(Value) -> true;
|
|
validate_update({description, Value}) when is_binary(Value) -> true;
|
|
validate_update({tags, Value}) when is_list(Value) -> true;
|
|
validate_update({type, Value}) when Value =:= personal; Value =:= commercial -> true;
|
|
validate_update({confirmation, Value}) ->
|
|
case Value of
|
|
auto -> true;
|
|
manual -> true;
|
|
{timeout, N} when is_integer(N), N > 0 -> true;
|
|
_ -> false
|
|
end;
|
|
validate_update(_) -> false.
|
|
|
|
%% ─── Административные функции ────────────────────────────────────────
|
|
-spec admin_list_all() -> {ok, [map()]} | {error, term()}.
|
|
admin_list_all() ->
|
|
Calendars = core_calendar:list_all(),
|
|
{ok, Calendars}.
|
|
|
|
-spec admin_get_by_id(binary()) -> {ok, #calendar{}} | {error, not_found}.
|
|
admin_get_by_id(CalendarId) ->
|
|
core_calendar:get_by_id(CalendarId).
|
|
|
|
-spec admin_update(binary(), map()) -> {ok, #calendar{}} | {error, term()}.
|
|
admin_update(CalendarId, Updates) when is_map(Updates) ->
|
|
%% Преобразуем map в список {атом, значение}, исключая служебные ключи
|
|
TupleList = maps:fold(fun key_to_update/3, [], Updates),
|
|
core_calendar:update(CalendarId, TupleList).
|
|
|
|
-spec admin_delete(binary()) -> ok | {error, term()}.
|
|
admin_delete(Id) ->
|
|
case core_calendar:delete(Id) of
|
|
{ok, _} -> ok;
|
|
Error -> Error
|
|
end.
|
|
|
|
key_to_update(<<"title">>, V, Acc) -> [{title, V} | Acc];
|
|
key_to_update(<<"description">>, V, Acc) -> [{description, V} | Acc];
|
|
key_to_update(<<"short_name">>, V, Acc) -> [{short_name, V} | Acc];
|
|
key_to_update(<<"category">>, V, Acc) -> [{category, V} | Acc];
|
|
key_to_update(<<"color">>, V, Acc) -> [{color, V} | Acc];
|
|
key_to_update(<<"image_url">>, V, Acc) -> [{image_url, V} | Acc];
|
|
key_to_update(<<"settings">>, V, Acc) -> [{settings, V} | Acc];
|
|
key_to_update(<<"tags">>, V, Acc) -> [{tags, V} | Acc];
|
|
key_to_update(<<"type">>, V, Acc) ->
|
|
Type = binary_to_existing_atom(V, utf8),
|
|
[{type, Type} | Acc];
|
|
key_to_update(<<"status">>, V, Acc) ->
|
|
Status = binary_to_existing_atom(V, utf8),
|
|
[{status, Status} | Acc];
|
|
key_to_update(<<"confirmation">>, V, Acc) ->
|
|
% confirmation может быть строкой "auto", "manual" или "timeout:N"
|
|
Conf = case V of
|
|
<<"auto">> -> auto;
|
|
<<"manual">> -> manual;
|
|
_ -> V % для сложных значений пока оставляем как есть
|
|
end,
|
|
[{confirmation, Conf} | Acc];
|
|
key_to_update(<<"reason">>, V, Acc) -> [{reason, V} | Acc];
|
|
key_to_update(_, _V, Acc) -> Acc. |