Рефакторинг обработчиков. Часть 1 #21

This commit is contained in:
2026-05-10 22:14:38 +03:00
parent a35d6f7acc
commit 6403f061df
46 changed files with 3082 additions and 2091 deletions
+39 -4
View File
@@ -1,14 +1,15 @@
-module(core_admin).
-include("records.hrl").
-export([create/3, get_by_email/1, get_by_id/1, list_all/0,
update_role/2, block/1, unblock/1, generate_id/0, update_last_login/1]).
update_role/2, block/1, unblock/1, update_last_login/1]).
-export([update/2]).
create(Email, Password, Role) ->
case get_by_email(Email) of
{ok, _} ->
{error, email_exists};
{error, not_found} ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
{ok, Hash} = argon2:hash(Password),
Now = calendar:universal_time(),
Admin = #admin{
@@ -24,6 +25,22 @@ create(Email, Password, Role) ->
{ok, Admin}
end.
%% Обновление администратора (любые поля)
update(AdminId, Updates) ->
F = fun() ->
case mnesia:read(admin, AdminId) of
[] -> {error, not_found};
[Admin] ->
UpdatedAdmin = apply_updates(Admin, Updates),
mnesia:write(UpdatedAdmin),
{ok, UpdatedAdmin}
end
end,
case mnesia:transaction(F) of
{atomic, Result} -> Result;
{aborted, Reason} -> {error, Reason}
end.
get_by_email(Email) ->
Match = #admin{email = Email, _ = '_'},
case mnesia:dirty_match_object(Match) of
@@ -73,5 +90,23 @@ update_status(Id, Status) ->
Error -> Error
end.
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
%%%===================================================================
%%% ВНУТРЕННИЕ ФУНКЦИИ
%%%===================================================================
apply_updates(Admin, []) -> Admin;
apply_updates(Admin, [{Field, Value} | Rest]) ->
NewAdmin = case Field of
email -> Admin#admin{email = Value};
password_hash -> Admin#admin{password_hash = Value};
role -> Admin#admin{role = Value};
status -> Admin#admin{status = Value};
nickname -> Admin#admin{nickname = Value};
avatar_url -> Admin#admin{avatar_url = Value};
timezone -> Admin#admin{timezone = Value};
language -> Admin#admin{language = Value};
phone -> Admin#admin{phone = Value};
preferences -> Admin#admin{preferences = Value};
_ -> Admin
end,
apply_updates(NewAdmin#admin{updated_at = calendar:universal_time()}, Rest).
+1 -1
View File
@@ -6,7 +6,7 @@
log(AdminId, Email, Role, Action, EntityType, EntityId, Ip) ->
log(AdminId, Email, Role, Action, EntityType, EntityId, Ip, undefined).
log(AdminId, Email, Role, Action, EntityType, EntityId, Ip, Reason) ->
Id = base64:encode(crypto:strong_rand_bytes(9)),
Id = infra_utils:generate_id(9),
Entry = #admin_audit{
id = Id,
admin_id = AdminId,
+2 -5
View File
@@ -10,7 +10,7 @@ list_banned_words() ->
mnesia:dirty_match_object(#banned_word{_ = '_'}).
add_banned_word(Word, AddedBy) ->
Id = generate_id(),
Id = infra_utils:generate_id(9),
Now = calendar:universal_time(),
BW = #banned_word{id = Id, word = Word, added_by = AddedBy, added_at = Now},
case mnesia:transaction(fun() ->
@@ -48,7 +48,4 @@ update_banned_word(OldWord, NewWord) ->
end) of
{atomic, {ok, UpdatedRec}} -> {ok, UpdatedRec};
{aborted, not_found} -> {error, not_found}
end.
generate_id() ->
base64:encode(crypto:strong_rand_bytes(9)).
end.
+2 -7
View File
@@ -3,12 +3,11 @@
-export([create/2, get_by_id/1, get_by_event_and_user/2, list_by_event/1, list_by_user/1]).
-export([update_status/2, delete/1]).
-export([generate_id/0]).
-export([count_bookings/0]).
%% Создание бронирования
create(EventId, UserId) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Booking = #booking{
id = Id,
event_id = EventId,
@@ -98,8 +97,4 @@ delete(Id) ->
{aborted, Reason} -> {error, Reason}
end.
count_bookings() -> mnesia:table_info(booking, size).
%% Внутренние функции
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
count_bookings() -> mnesia:table_info(booking, size).
+2 -7
View File
@@ -1,13 +1,12 @@
-module(core_calendar).
-include("records.hrl").
-export([create/4, create/5, get_by_id/1, list_by_owner/1, update/2, delete/1]).
-export([generate_id/0]).
-export([count_calendars/0]).
-export([freeze/2, unfreeze/2]). % ← новые функции
%% Создание календаря
create(OwnerId, Title, Description, Confirmation) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Calendar = #calendar{
id = Id,
owner_id = OwnerId,
@@ -30,7 +29,7 @@ create(OwnerId, Title, Description, Confirmation) ->
%% Создание календаря с типом и политикой
create(OwnerId, Title, Description, Confirmation, Type) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Calendar = #calendar{
id = Id,
owner_id = OwnerId,
@@ -94,10 +93,6 @@ freeze(Id, Reason) ->
unfreeze(Id, Reason) ->
update(Id, [{status, active}, {reason, Reason}]).
%% Внутренние функции
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
apply_updates(Calendar, Updates) ->
Updated = lists:foldl(fun({Field, Value}, C) ->
set_field(Field, Value, C)
+3 -8
View File
@@ -3,14 +3,13 @@
-export([create/4, create_recurring/5, get_by_id/1, list_by_calendar/1,
update/2, delete/1, materialize_occurrence/3]).
-export([generate_id/0]).
-export([count_events/0, count_events_by_date/2]).
-export([freeze/2, unfreeze/2]).
-export([list_all/0]).
%% Создание одиночного события
create(CalendarId, Title, StartTime, Duration) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Event = #event{
id = Id,
calendar_id = CalendarId,
@@ -46,7 +45,7 @@ create(CalendarId, Title, StartTime, Duration) ->
%% Создание повторяющегося события (мастер-запись)
create_recurring(CalendarId, Title, StartTime, Duration, RRule) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Event = #event{
id = Id,
calendar_id = CalendarId,
@@ -94,7 +93,7 @@ materialize_occurrence(MasterId, OccurrenceStart, SpecialistId) ->
case Existing of
[] ->
% Создаём новый экземпляр
InstanceId = generate_id(),
InstanceId = infra_utils:generate_id(16),
Instance = #event{
id = InstanceId,
calendar_id = Master#event.calendar_id,
@@ -193,10 +192,6 @@ count_events_by_date(From, To) ->
date_part({{Y,M,D}, _}) -> {Y,M,D}.
%% Внутренние функции
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
apply_updates(Event, Updates) ->
Updated = lists:foldl(fun({Field, Value}, E) ->
set_field(Field, Value, E)
+39 -3
View File
@@ -6,10 +6,11 @@
-export([generate_id/0]).
-export([count_reports_by_status/1, count_reports_by_admin/2]).
-export([count_reports_resolved_by_admin/2, avg_resolution_time/1]).
-export([delete/1, update/2]). % <-- добавлено
%% Создание жалобы
create(ReporterId, TargetType, TargetId, Reason) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Report = #report{
id = Id,
reporter_id = ReporterId,
@@ -109,6 +110,41 @@ avg_resolution_time(Status) ->
TotalSeconds / length(Resolved) / 3600.0
end.
%% Внутренние функции
%% Мягкое удаление жалобы (просто физически удаляем запись)
-spec delete(binary()) -> {ok, deleted} | {error, not_found}.
delete(Id) ->
case get_by_id(Id) of
{ok, _} ->
mnesia:dirty_delete(report, Id),
{ok, deleted};
Error -> Error
end.
%% Обновление произвольных полей жалобы (для административных целей)
-spec update(binary(), proplists:proplist()) -> {ok, #report{}} | {error, not_found}.
update(Id, Updates) ->
case get_by_id(Id) of
{ok, Report} ->
UpdatedReport = apply_updates(Report, Updates),
mnesia:dirty_write(UpdatedReport),
{ok, UpdatedReport};
Error -> Error
end.
%%%===================================================================
%%% Внутренние функции
%%%===================================================================
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
apply_updates(Report, []) -> Report;
apply_updates(Report, [{Field, Value} | Rest]) ->
NewReport = case Field of
status -> Report#report{status = Value};
resolved_at -> Report#report{resolved_at = Value};
resolved_by -> Report#report{resolved_by = Value};
reason -> Report#report{reason = Value};
_ -> Report
end,
apply_updates(NewReport, Rest).
+1 -6
View File
@@ -4,12 +4,11 @@
-export([create/5, get_by_id/1, list_by_target/2, list_by_user/1,
update/2, delete/1, hide/2, unhide/2]).
-export([get_average_rating/2, has_user_reviewed/3]).
-export([generate_id/0]).
-export([count_reviews/0, list_all/0]).
%% Создание отзыва
create(UserId, TargetType, TargetId, Rating, Comment) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Review = #review{
id = Id,
user_id = UserId,
@@ -117,10 +116,6 @@ count_reviews() -> mnesia:table_info(review, size).
list_all() -> mnesia:dirty_match_object(#review{_ = '_'}).
%% Внутренние функции
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
apply_updates(Review, Updates) ->
Updated = lists:foldl(fun({Field, Value}, R) ->
set_field(Field, Value, R)
+1 -6
View File
@@ -3,7 +3,6 @@
-export([create/3, get_by_id/1, get_active_by_user/1, list_by_user/1, list_all/0]).
-export([update_status/2, check_expired/0]).
-export([generate_id/0]).
% --------------- новые обёртки для админки ------------------
-export([list_subscriptions/0,
create_subscription/1,
@@ -16,7 +15,7 @@
%% Создание подписки
create(UserId, Plan, TrialUsed) ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
Now = calendar:universal_time(),
{StartDate, EndDate} = case TrialUsed of
@@ -129,10 +128,6 @@ downgrade_user_calendars(UserId) ->
core_calendar:update(Cal#calendar.id, [{type, personal}])
end, Calendars).
%% Внутренние функции
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
plan_to_months(monthly) -> 1;
plan_to_months(quarterly) -> 3;
plan_to_months(biannual) -> 6;
+2 -2
View File
@@ -48,7 +48,7 @@ stats() ->
%% ── новые функции ──────────────────────────────────────
create_ticket(Data) ->
Id = base64:encode(crypto:strong_rand_bytes(9), #{mode => urlsafe, padding => false}),
Id = infra_utils:generate_id(9),
Now = calendar:universal_time(),
Ticket = #ticket{
id = Id,
@@ -103,4 +103,4 @@ apply_updates(Ticket, Updates) ->
<<"context">> -> Acc#ticket{context = Value};
_ -> Acc
end
end, Ticket, maps:to_list(Updates)).
end, Ticket, maps:to_list(Updates)).
+7 -8
View File
@@ -3,10 +3,9 @@
-export([create/2, get_by_id/1, get_by_email/1, update/2, update_status/3, delete/1, update_last_login/1]).
-export([email_exists/1]).
-export([generate_id/0]).
-export([list_users/0]).
-export([block/2, unblock/2]).
-export([count_users/0, count_users_by_date/2]).
-export([count_users/0, count_users_by_date/2, list_all/0]).
-export([create_bot/2, delete_bot/1]).
%% Создание пользователя
@@ -16,7 +15,7 @@ create(Email, Password) ->
true ->
{error, email_exists};
false ->
Id = generate_id(),
Id = infra_utils:generate_id(16),
{ok, PasswordHash} = logic_auth:hash_password(Password),
User = #user{
@@ -150,6 +149,10 @@ unblock(Id, Reason) ->
count_users() ->
mnesia:table_info(user, size).
%% Административный список (все пользователи, без фильтрации)
list_all() ->
mnesia:dirty_match_object(#user{_ = '_'}).
count_users_by_date(From, To) ->
All = mnesia:dirty_match_object(#user{_ = '_'}),
Filtered = lists:filter(fun(U) ->
@@ -166,10 +169,6 @@ count_users_by_date(From, To) ->
date_part({{Y,M,D}, _}) -> {Y,M,D}.
%% Внутренние функции
generate_id() ->
base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}).
apply_updates(User, Updates) ->
Updated = lists:foldl(fun({Field, Value}, U) ->
set_field(Field, Value, U)
@@ -196,7 +195,7 @@ create_bot(Email, Password) ->
case mnesia:dirty_index_read(user, Email, email) of
[] ->
{ok, PasswordHash} = logic_auth:hash_password(Password),
Id = generate_id(),
Id = infra_utils:generate_id(16),
User = #user{
id = Id,
email = Email,