Добавить авто-регистрацию тикетов (hash/dedupe/500/WS). Refs EventHub/EventHubBack#35
CI / test (push) Successful in 21m45s
CI / deploy-ift (push) Successful in 6m8s
CI / e2e-ift (push) Failing after 6m13s
CI / deploy-stage (push) Has been skipped
CI / e2e-stage (push) Has been skipped

This commit is contained in:
2026-07-17 00:44:09 +03:00
parent 0a52712258
commit a696d25486
12 changed files with 590 additions and 59 deletions
+14 -3
View File
@@ -21,6 +21,7 @@ trails() ->
tags => [<<"Tickets">>],
parameters => [
#{name => <<"status">>, in => <<"query">>, schema => #{type => string, enum => [<<"open">>, <<"in_progress">>, <<"resolved">>, <<"closed">>]}, description => <<"Filter by status">>},
#{name => <<"source">>, in => <<"query">>, schema => #{type => string, enum => [<<"backend">>, <<"frontend">>, <<"manual">>]}, description => <<"Filter by source">>},
#{name => <<"assigned_to">>, in => <<"query">>, schema => #{type => string}, description => <<"Filter by assigned admin ID">>},
#{name => <<"q">>, in => <<"query">>, schema => #{type => string}, description => <<"Search in error_message">>},
#{name => <<"sort">>, in => <<"query">>, schema => #{type => string, enum => [<<"first_seen">>, <<"last_seen">>, <<"status">>]}, description => <<"Sort field">>},
@@ -65,7 +66,8 @@ ticket_schema() ->
last_seen => #{type => string, format => <<"date-time">>},
status => #{type => string, enum => [<<"open">>, <<"in_progress">>, <<"resolved">>, <<"closed">>]},
assigned_to => #{type => string, nullable => true},
resolution_note => #{type => string, nullable => true}
resolution_note => #{type => string, nullable => true},
source => #{type => string, enum => [<<"backend">>, <<"frontend">>, <<"manual">>]}
}
}.
@@ -144,22 +146,31 @@ parse_ticket_filters(Req) ->
Qs = cowboy_req:parse_qs(Req),
#{
status => proplists:get_value(<<"status">>, Qs),
source => proplists:get_value(<<"source">>, Qs),
assigned_to => proplists:get_value(<<"assigned_to">>, Qs),
q => proplists:get_value(<<"q">>, Qs)
}.
apply_ticket_filters(Tickets, Filters) ->
Assigned = maps:get(assigned_to, Filters, undefined),
Source = maps:get(source, Filters, undefined),
Q = maps:get(q, Filters, undefined),
F1 = case Assigned of
F0 = case Source of
undefined -> Tickets;
_ -> [T || T <- Tickets, T#ticket.assigned_to =:= Assigned]
_ -> [T || T <- Tickets, ticket_source(T) =:= Source]
end,
F1 = case Assigned of
undefined -> F0;
_ -> [T || T <- F0, T#ticket.assigned_to =:= Assigned]
end,
case Q of
undefined -> F1;
_ -> [T || T <- F1, string:str(binary_to_list(T#ticket.error_message), binary_to_list(Q)) > 0]
end.
ticket_source(#ticket{source = S}) when is_binary(S), S =/= <<>> -> S;
ticket_source(_) -> <<"backend">>.
sort_tickets(Tickets, #{sort := Sort, order := Order}) ->
Field = binary_to_existing_atom(Sort, utf8),
lists:sort(