Files
EventHubBack/src/logic/logic_ticket.erl
T
2026-07-13 14:53:51 +03:00

155 lines
5.1 KiB
Erlang

-module(logic_ticket).
-include("records.hrl").
-export([report_error/3,
get_ticket/2,
list_tickets/1,
list_tickets_by_status/2,
update_status/3,
assign_ticket/3,
resolve_ticket/3,
close_ticket/2,
get_statistics/1]).
-export([delete_ticket/2]).
-export([get_user_ticket/2]).
%% Зарегистрировать ошибку (создать или обновить тикет)
report_error(ErrorMessage, Stacktrace, Context) ->
Existing = [T || T <- core_ticket:list_all(), T#ticket.error_message =:= ErrorMessage],
case Existing of
[Ticket] ->
% Увеличить счётчик и обновить last_seen
Updated = Ticket#ticket{
count = Ticket#ticket.count + 1,
last_seen = calendar:universal_time()
},
mnesia:dirty_write(Updated),
{ok, Updated};
[] ->
ReporterId = maps:get(<<"reporter_id">>, Context,
maps:get(reporter_id, Context, <<"anonymous">>)),
Data = #{
<<"reporter_id">> => ReporterId,
<<"error_message">> => ErrorMessage,
<<"stacktrace">> => Stacktrace,
<<"context">> => list_to_binary(io_lib:format("~p", [Context]))
},
case core_ticket:create_ticket(Data) of
{ok, Ticket} = Result ->
% Уведомление администраторов (заглушка)
notify_admins(Ticket),
Result;
Error -> Error
end
end.
%% Получить тикет, проверяя, что пользователь является репортером
get_user_ticket(UserId, TicketId) ->
case core_ticket:get_by_id(TicketId) of % используем базовую функцию без проверки прав
{ok, Ticket} ->
case Ticket#ticket.reporter_id =:= UserId of
true -> {ok, Ticket};
false -> {error, access_denied}
end;
Error -> Error
end.
%% Получить тикет (только для админов)
get_ticket(AdminId, TicketId) ->
case admin_utils:is_admin(AdminId) of
true -> core_ticket:get_by_id(TicketId);
false -> {error, access_denied}
end.
%% Список всех тикетов (только для админов)
list_tickets(AdminId) ->
case admin_utils:is_admin(AdminId) of
true -> core_ticket:list_all();
false -> {error, access_denied}
end.
%% Список тикетов по статусу (только для админов)
list_tickets_by_status(AdminId, Status) ->
case admin_utils:is_admin(AdminId) of
true ->
All = core_ticket:list_all(),
[T || T <- All, T#ticket.status =:= Status];
false -> {error, access_denied}
end.
%% Обновить статус тикета
update_status(AdminId, TicketId, closed) ->
close_ticket(AdminId, TicketId);
update_status(AdminId, TicketId, Status) ->
case admin_utils:is_admin(AdminId) of
true -> core_ticket:update_ticket(TicketId, #{<<"status">> => Status});
false -> {error, access_denied}
end.
%% Назначить тикет администратору
assign_ticket(AdminId, TicketId, AssignToId) ->
case admin_utils:is_admin(AdminId) of
true -> core_ticket:update_ticket(TicketId, #{<<"assigned_to">> => AssignToId});
false -> {error, access_denied}
end.
%% Отметить тикет как решённый с примечанием
resolve_ticket(AdminId, TicketId, ResolutionNote) ->
case admin_utils:is_admin(AdminId) of
true ->
core_ticket:update_ticket(TicketId, #{
<<"status">> => <<"resolved">>,
<<"resolution_note">> => ResolutionNote,
<<"closed_at">> => calendar:universal_time()
});
false -> {error, access_denied}
end.
%% Закрыть тикет
close_ticket(AdminId, TicketId) ->
case admin_utils:is_admin(AdminId) of
true -> core_ticket:close(TicketId, AdminId);
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
true ->
All = core_ticket:list_all(),
Open = count_by_status(All, open),
InProgress = count_by_status(All, in_progress),
Resolved = count_by_status(All, resolved),
Closed = count_by_status(All, closed),
TotalErrors = lists:sum([T#ticket.count || T <- All]),
#{
total_tickets => length(All),
open => Open,
in_progress => InProgress,
resolved => Resolved,
closed => Closed,
total_errors => TotalErrors
};
false -> {error, access_denied}
end.
count_by_status(Tickets, Status) ->
length([T || T <- Tickets, normalize_status(T#ticket.status) =:= Status]).
normalize_status(Status) when is_atom(Status) -> Status;
normalize_status(Status) when is_binary(Status) ->
try binary_to_existing_atom(Status, utf8)
catch error:badarg -> Status
end.
%% ============ Вспомогательные функции ============
notify_admins(_Ticket) ->
ok.