%%%------------------------------------------------------------------- %%% @doc Административный обработчик статистики по календарям. %%% GET /v1/admin/calendars/stats %%% @end %%%------------------------------------------------------------------- -module(admin_handler_calendar_stats). -behaviour(cowboy_handler). -export([init/2]). -export([trails/0]). -include("records.hrl"). -spec init(cowboy_req:req(), any()) -> {ok, cowboy_req:req(), any()}. init(Req, _Opts) -> case cowboy_req:method(Req) of <<"GET">> -> get_calendar_stats(Req); _ -> handler_utils:send_error(Req, 405, <<"Method not allowed">>) end. -spec trails() -> [map()]. trails() -> [ #{ path => <<"/v1/admin/calendars/stats">>, method => <<"GET">>, description => <<"Calendar statistics">>, tags => [<<"Statistics">>], responses => #{ 200 => #{ description => <<"Calendar statistics object">>, content => #{<<"application/json">> => #{schema => calendar_stats_schema()}} } } } ]. calendar_stats_schema() -> #{ type => object, properties => #{ <<"total_calendars">> => #{type => integer}, <<"calendars_by_type">> => #{ type => object, additionalProperties => #{type => integer} }, <<"calendars_by_status">> => #{ type => object, additionalProperties => #{type => integer} }, <<"top_calendars_by_reviews">> => #{ type => array, items => calendar_rank_schema() }, <<"top_calendars_by_positive_reviews">> => #{ type => array, items => calendar_rank_schema() }, <<"top_calendars_by_negative_reviews">> => #{ type => array, items => calendar_rank_schema() }, <<"top_calendars_by_rating">> => #{ type => array, items => calendar_rank_schema() } } }. calendar_rank_schema() -> #{ type => object, properties => #{ <<"id">> => #{type => string}, <<"title">> => #{type => string}, <<"rating_avg">> => #{type => number, format => float}, <<"review_count">> => #{type => integer} } }. %%% Internal functions get_calendar_stats(Req) -> case handler_utils:auth_admin(Req) of {ok, _AdminId, Req1} -> Total = core_calendar:count_calendars(), ByType = core_calendar:count_calendars_by_type(), ByStatus = core_calendar:count_calendars_by_status(), TopReviews = core_calendar:get_top_calendars_by_reviews(10), TopPositive = core_calendar:get_top_calendars_by_positive_reviews(10), TopNegative = core_calendar:get_top_calendars_by_negative_reviews(10), TopRating = core_calendar:get_top_calendars_by_rating(10), Stats = #{ <<"total_calendars">> => Total, <<"calendars_by_type">> => maps:from_list([{atom_to_binary(T, utf8), C} || {T, C} <- ByType]), <<"calendars_by_status">> => maps:from_list([{atom_to_binary(S, utf8), C} || {S, C} <- ByStatus]), <<"top_calendars_by_reviews">> => format_calendar_list(TopReviews), <<"top_calendars_by_positive_reviews">> => format_calendar_list(TopPositive), <<"top_calendars_by_negative_reviews">> => format_calendar_list(TopNegative), <<"top_calendars_by_rating">> => format_calendar_list(TopRating) }, handler_utils:send_json(Req1, 200, Stats); {error, Code, Msg, Req1} -> handler_utils:send_error(Req1, Code, Msg) end. format_calendar_list(List) -> lists:map(fun(#calendar{id = Id, title = Title, rating_avg = RAvg}) -> #{<<"id">> => Id, <<"title">> => Title, <<"rating_avg">> => RAvg} end, List).