Рефакторинг обработчиков. Часть 1 #21
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
-module(logic_admin).
|
||||
|
||||
-export([list_admins/2, get_admin/1, update_admin/2]).
|
||||
|
||||
-include("records.hrl").
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Административный список администраторов с пагинацией
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec list_admins(map(), #{limit => integer(), offset => integer(), sort => binary(), order => binary()}) ->
|
||||
{ok, non_neg_integer(), [#admin{}]}.
|
||||
list_admins(Filters, Pagination) ->
|
||||
#{limit := Limit, offset := Offset, sort := Sort, order := Order} = Pagination,
|
||||
AllAdmins = core_admin:list_all(),
|
||||
Filtered = apply_filters(AllAdmins, Filters),
|
||||
Sorted = sort_admins(Filtered, Sort, Order),
|
||||
Total = length(Sorted),
|
||||
Page = lists:sublist(Sorted, Offset + 1, Limit),
|
||||
{ok, Total, Page}.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Получение администратора по ID
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec get_admin(binary()) -> {ok, #admin{}} | {error, not_found}.
|
||||
get_admin(AdminId) ->
|
||||
core_admin:get_by_id(AdminId).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Обновление администратора
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec update_admin(binary(), proplists:proplist()) ->
|
||||
{ok, #admin{}} | {error, not_found | invalid_field}.
|
||||
update_admin(AdminId, Updates) ->
|
||||
case core_admin:get_by_id(AdminId) of
|
||||
{ok, _Admin} ->
|
||||
ValidUpdates = validate_admin_updates(Updates),
|
||||
core_admin:update(AdminId, ValidUpdates);
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Внутренние функции
|
||||
%%%===================================================================
|
||||
|
||||
apply_filters(Admins, Filters) ->
|
||||
Role = maps:get(role, Filters, undefined),
|
||||
Status = maps:get(status, Filters, undefined),
|
||||
F1 = case Role of
|
||||
undefined -> Admins;
|
||||
_ -> [A || A <- Admins, A#admin.role =:= Role]
|
||||
end,
|
||||
case Status of
|
||||
undefined -> F1;
|
||||
_ -> [A || A <- F1, A#admin.status =:= Status]
|
||||
end.
|
||||
|
||||
sort_admins(Admins, SortField, Order) ->
|
||||
Field = binary_to_existing_atom(SortField, utf8),
|
||||
Sorted = lists:sort(
|
||||
fun(A, B) ->
|
||||
ValA = admin_field(A, Field),
|
||||
ValB = admin_field(B, Field),
|
||||
if Order == <<"asc">> -> ValA =< ValB;
|
||||
true -> ValA >= ValB
|
||||
end
|
||||
end, Admins),
|
||||
Sorted.
|
||||
|
||||
admin_field(#admin{created_at = V}, created_at) -> V;
|
||||
admin_field(#admin{email = V}, email) -> V;
|
||||
admin_field(#admin{role = V}, role) -> V;
|
||||
admin_field(_, _) -> undefined.
|
||||
|
||||
validate_admin_updates(Updates) ->
|
||||
lists:filter(fun validate_admin_update/1, Updates).
|
||||
|
||||
validate_admin_update({nickname, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_admin_update({avatar_url, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_admin_update({timezone, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_admin_update({language, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_admin_update({phone, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_admin_update({preferences, V}) when is_map(V); V =:= undefined -> true;
|
||||
validate_admin_update(_) -> false.
|
||||
@@ -0,0 +1,47 @@
|
||||
-module(logic_report).
|
||||
-include("records.hrl").
|
||||
|
||||
-export([list_reports/1, get_report/2, update_report_status/3, delete_report/2]).
|
||||
|
||||
%% Получить список всех жалоб (только для админов)
|
||||
-spec list_reports(binary()) -> {ok, [#report{}]} | {error, access_denied}.
|
||||
list_reports(AdminId) ->
|
||||
case admin_utils:is_admin(AdminId) of
|
||||
true ->
|
||||
{ok, Reports} = core_report:list_all(),
|
||||
{ok, Reports};
|
||||
false -> {error, access_denied}
|
||||
end.
|
||||
|
||||
%% Получить конкретную жалобу по ID (только для админов)
|
||||
-spec get_report(binary(), binary()) -> {ok, #report{}} | {error, not_found | access_denied}.
|
||||
get_report(AdminId, ReportId) ->
|
||||
case admin_utils:is_admin(AdminId) of
|
||||
true -> core_report:get_by_id(ReportId);
|
||||
false -> {error, access_denied}
|
||||
end.
|
||||
|
||||
%% Обновить статус жалобы (только для админов)
|
||||
-spec update_report_status(binary(), binary(), binary()) -> {ok, #report{}} | {error, not_found | access_denied | invalid_status}.
|
||||
update_report_status(AdminId, ReportId, NewStatus) ->
|
||||
case admin_utils:is_admin(AdminId) of
|
||||
true ->
|
||||
StatusAtom = case NewStatus of
|
||||
<<"reviewed">> -> reviewed;
|
||||
<<"dismissed">> -> dismissed;
|
||||
_ -> undefined
|
||||
end,
|
||||
case StatusAtom of
|
||||
undefined -> {error, invalid_status};
|
||||
_ -> core_report:update_status(ReportId, StatusAtom, AdminId)
|
||||
end;
|
||||
false -> {error, access_denied}
|
||||
end.
|
||||
|
||||
%% Удалить жалобу (только для админов)
|
||||
-spec delete_report(binary(), binary()) -> {ok, deleted} | {error, not_found | access_denied}.
|
||||
delete_report(AdminId, ReportId) ->
|
||||
case admin_utils:is_admin(AdminId) of
|
||||
true -> core_report:delete(ReportId);
|
||||
false -> {error, access_denied}
|
||||
end.
|
||||
@@ -5,6 +5,7 @@
|
||||
update_review/3, delete_review/2, hide_review/2, hide_review/3, unhide_review/2, unhide_review/3]).
|
||||
-export([can_review/3, update_target_rating/2, can_moderate_review/2]).
|
||||
-export([list_admin_reviews/1, bulk_update_status/1]).
|
||||
-export([list_admin_reviews/2, get_review_admin/1, update_review_admin/2]).
|
||||
|
||||
%% Создание отзыва
|
||||
create_review(UserId, TargetType, TargetId, Rating, Comment) ->
|
||||
@@ -200,8 +201,9 @@ can_moderate_review(UserId, ReviewId) ->
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
list_admin_reviews(Filters) ->
|
||||
AllReviews = core_review:list_all(),
|
||||
apply_filters(AllReviews, Filters).
|
||||
Reviews = core_review:list_all(), % возвращает список
|
||||
Filtered = apply_filters(Reviews, Filters),
|
||||
{ok, Filtered}.
|
||||
|
||||
%% Вспомогательная функция: фильтрация списка по proplist
|
||||
apply_filters(Reviews, []) ->
|
||||
@@ -271,4 +273,53 @@ update_target_rating(event, EventId) ->
|
||||
update_target_rating(calendar, CalendarId) ->
|
||||
{Avg, Count} = core_review:get_average_rating(calendar, CalendarId),
|
||||
core_calendar:update(CalendarId, [{rating_avg, Avg}, {rating_count, Count}]);
|
||||
update_target_rating(_, _) -> ok.
|
||||
update_target_rating(_, _) -> ok.
|
||||
|
||||
%% Административный список с пагинацией
|
||||
-spec list_admin_reviews(map(), #{limit => integer(), offset => integer(), sort => binary(), order => binary()}) ->
|
||||
{ok, non_neg_integer(), [#review{}]}.
|
||||
list_admin_reviews(Filters, Pagination) ->
|
||||
#{limit := Limit, offset := Offset, sort := Sort, order := Order} = Pagination,
|
||||
% Получаем все отзывы (можно временно через list_admin_reviews/1)
|
||||
{ok, All} = list_admin_reviews(maps:to_list(Filters)),
|
||||
Sorted = sort_reviews(All, Sort, Order),
|
||||
Total = length(Sorted),
|
||||
Page = lists:sublist(Sorted, Offset + 1, Limit),
|
||||
{ok, Total, Page}.
|
||||
|
||||
%% Получить отзыв без проверки прав
|
||||
-spec get_review_admin(binary()) -> {ok, #review{}} | {error, not_found}.
|
||||
get_review_admin(ReviewId) ->
|
||||
core_review:get_by_id(ReviewId).
|
||||
|
||||
%% Обновить отзыв без проверки прав
|
||||
-spec update_review_admin(binary(), proplists:proplist()) ->
|
||||
{ok, #review{}} | {error, not_found}.
|
||||
update_review_admin(ReviewId, Updates) ->
|
||||
case core_review:get_by_id(ReviewId) of
|
||||
{ok, _} -> core_review:update(ReviewId, Updates);
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Вспомогательные функции административной пагинации
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
%% @private Сортирует список отзывов по указанному полю.
|
||||
sort_reviews(Reviews, SortField, Order) ->
|
||||
Field = binary_to_existing_atom(SortField, utf8),
|
||||
Sorted = lists:sort(
|
||||
fun(A, B) ->
|
||||
ValA = review_field(A, Field),
|
||||
ValB = review_field(B, Field),
|
||||
if Order == <<"asc">> -> ValA =< ValB;
|
||||
true -> ValA >= ValB
|
||||
end
|
||||
end, Reviews),
|
||||
Sorted.
|
||||
|
||||
%% @private Извлекает значение поля из записи отзыва для сортировки.
|
||||
review_field(#review{created_at = V}, created_at) -> V;
|
||||
review_field(#review{rating = V}, rating) -> V;
|
||||
review_field(#review{status = V}, status) -> V;
|
||||
review_field(_, _) -> undefined.
|
||||
@@ -10,6 +10,7 @@
|
||||
resolve_ticket/3,
|
||||
close_ticket/2,
|
||||
get_statistics/1]).
|
||||
-export([delete_ticket/2]).
|
||||
|
||||
%% Зарегистрировать ошибку (создать или обновить тикет)
|
||||
report_error(ErrorMessage, Stacktrace, Context) ->
|
||||
@@ -93,6 +94,13 @@ close_ticket(AdminId, TicketId) ->
|
||||
false -> {error, access_denied}
|
||||
end.
|
||||
|
||||
%% Удалить тикет (только для админов)
|
||||
delete_ticket(AdminId, TicketId) ->
|
||||
case admin_utils:is_admin(AdminId) of
|
||||
true -> core_ticket:delete_ticket(TicketId);
|
||||
false -> {error, access_denied}
|
||||
end.
|
||||
|
||||
%% Получить статистику по тикетам
|
||||
get_statistics(AdminId) ->
|
||||
case admin_utils:is_admin(AdminId) of
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
-module(logic_user).
|
||||
|
||||
-export([list_users_admin/2, get_user_admin/1, update_user_admin/2, delete_user_admin/1]).
|
||||
|
||||
-include("records.hrl").
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Административный список пользователей с пагинацией
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec list_users_admin(map(), #{limit => integer(), offset => integer(), sort => binary(), order => binary()}) ->
|
||||
{ok, non_neg_integer(), [#user{}]}.
|
||||
list_users_admin(Filters, Pagination) ->
|
||||
#{limit := Limit, offset := Offset, sort := Sort, order := Order} = Pagination,
|
||||
AllUsers = core_user:list_all(),
|
||||
Filtered = apply_filters(AllUsers, Filters),
|
||||
Sorted = sort_users(Filtered, Sort, Order),
|
||||
Total = length(Sorted),
|
||||
Page = lists:sublist(Sorted, Offset + 1, Limit),
|
||||
{ok, Total, Page}.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Получение пользователя по ID (без проверки прав)
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec get_user_admin(binary()) -> {ok, #user{}} | {error, not_found}.
|
||||
get_user_admin(UserId) ->
|
||||
core_user:get_by_id(UserId).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Обновление пользователя (без проверки прав)
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec update_user_admin(binary(), proplists:proplist()) ->
|
||||
{ok, #user{}} | {error, not_found | invalid_field}.
|
||||
update_user_admin(UserId, Updates) ->
|
||||
case core_user:get_by_id(UserId) of
|
||||
{ok, _User} ->
|
||||
ValidUpdates = validate_user_updates(Updates),
|
||||
core_user:update(UserId, ValidUpdates);
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Мягкое удаление пользователя (установка статуса deleted)
|
||||
%%%-------------------------------------------------------------------
|
||||
-spec delete_user_admin(binary()) -> {ok, #user{}} | {error, not_found}.
|
||||
delete_user_admin(UserId) ->
|
||||
case core_user:get_by_id(UserId) of
|
||||
{ok, User} ->
|
||||
UpdatedUser = User#user{status = deleted},
|
||||
core_user:update(UserId, UpdatedUser);
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Внутренние функции
|
||||
%%%===================================================================
|
||||
|
||||
apply_filters(Users, Filters) ->
|
||||
Role = maps:get(role, Filters, undefined),
|
||||
Status = maps:get(status, Filters, undefined),
|
||||
Q = maps:get(q, Filters, undefined),
|
||||
F1 = case Role of
|
||||
undefined -> Users;
|
||||
_ -> [U || U <- Users, U#user.role =:= Role]
|
||||
end,
|
||||
F2 = case Status of
|
||||
undefined -> F1;
|
||||
_ -> [U || U <- F1, U#user.status =:= Status]
|
||||
end,
|
||||
case Q of
|
||||
undefined -> F2;
|
||||
_ -> [U || U <- F2,
|
||||
string:str(binary_to_list(U#user.email), binary_to_list(Q)) > 0 orelse
|
||||
(U#user.nickname /= undefined andalso string:str(binary_to_list(U#user.nickname), binary_to_list(Q)) > 0)]
|
||||
end.
|
||||
|
||||
sort_users(Users, SortField, Order) ->
|
||||
Field = binary_to_existing_atom(SortField, utf8),
|
||||
Sorted = lists:sort(
|
||||
fun(A, B) ->
|
||||
ValA = user_field(A, Field),
|
||||
ValB = user_field(B, Field),
|
||||
if Order == <<"asc">> -> ValA =< ValB;
|
||||
true -> ValA >= ValB
|
||||
end
|
||||
end, Users),
|
||||
Sorted.
|
||||
|
||||
user_field(#user{created_at = V}, created_at) -> V;
|
||||
user_field(#user{email = V}, email) -> V;
|
||||
user_field(#user{role = V}, role) -> V;
|
||||
user_field(#user{status = V}, status) -> V;
|
||||
user_field(_, _) -> undefined.
|
||||
|
||||
validate_user_updates(Updates) ->
|
||||
lists:filter(fun validate_user_update/1, Updates).
|
||||
|
||||
validate_user_update({role, V}) when V =:= user; V =:= bot -> true;
|
||||
validate_user_update({status, V}) when V =:= active; V =:= frozen; V =:= deleted -> true;
|
||||
validate_user_update({reason, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_user_update({nickname, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_user_update({timezone, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_user_update({language, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_user_update({phone, V}) when is_binary(V); V =:= undefined -> true;
|
||||
validate_user_update({preferences, V}) when is_map(V); V =:= undefined -> true;
|
||||
validate_user_update(_) -> false.
|
||||
Reference in New Issue
Block a user