137 lines
4.0 KiB
Elixir
137 lines
4.0 KiB
Elixir
defmodule Api.Studies do
|
|
import Ecto.Query
|
|
alias Api.Repo
|
|
|
|
def studies_sql_query(filters) do
|
|
page = filters["page"] || 1
|
|
size = filters["size"] || 24
|
|
|
|
filter = filters["filter"] || []
|
|
sort = filters["sort"] || [%{"dir" => "desc", "field" => "studydate"}]
|
|
|
|
|
|
|
|
# Construcción de condiciones de filtro dinámicas
|
|
filter_conditions =
|
|
Enum.reduce(filter, dynamic(true), fn f, acc ->
|
|
field = f["field"]
|
|
value = f["value"]
|
|
|
|
condition =
|
|
case field do
|
|
"modality" ->
|
|
dynamic([s], ilike(s.modality, ^"%#{value}%"))
|
|
|
|
"idstudy" ->
|
|
dynamic([s], s.idstudy == ^String.to_integer(value))
|
|
|
|
"studydate" ->
|
|
dynamic([s], fragment("CAST(? AS DATE)::text LIKE ?", s.studydate, ^"%#{value}%"))
|
|
|
|
"studydate_start" ->
|
|
if value == "" do
|
|
dynamic(true)
|
|
else
|
|
dynamic([s], fragment("CAST(? AS DATE)::text", s.studydate) >= ^value)
|
|
end
|
|
|
|
"studydate_end" ->
|
|
if value == "" do
|
|
dynamic(true)
|
|
else
|
|
dynamic([s], fragment("CAST(? AS DATE)::text", s.studydate) <= ^value)
|
|
end
|
|
|
|
"accessionnumber" ->
|
|
dynamic([s], ilike(s.accessionnumber, ^"%#{value}%"))
|
|
|
|
"proceduredescription" ->
|
|
dynamic([s], ilike(s.studydescription, ^"%#{value}%"))
|
|
|
|
"insurer" ->
|
|
dynamic([s], ilike(s.insurer, ^"%#{value}%"))
|
|
|
|
"sitename" ->
|
|
dynamic([s], ilike(s.institutionname, ^"%#{value}%"))
|
|
|
|
"nrodocumento" ->
|
|
dynamic([s, p], ilike(p.patientid, ^"%#{value}%"))
|
|
|
|
"patientname" ->
|
|
dynamic([s, p], ilike(p.patientname, ^"%#{value}%"))
|
|
|
|
"region" ->
|
|
dynamic([s], s.region == ^value)
|
|
|
|
"studytime" ->
|
|
dynamic([s], fragment("CAST(? AS TIME)::text LIKE ?", s.studytime, ^"#{value}%"))
|
|
|
|
_ ->
|
|
dynamic(true)
|
|
end
|
|
|
|
# Combina las condiciones dinámicas
|
|
dynamic([s, p], ^condition and ^acc)
|
|
end)
|
|
|
|
sort_conditions =
|
|
Enum.map(sort, fn v ->
|
|
direction = String.to_atom(v["dir"])
|
|
field = String.to_atom(v["field"])
|
|
|
|
{direction, field}
|
|
end)
|
|
|
|
|
|
query =
|
|
from s in "study",
|
|
join: p in "patient",
|
|
on: p.idpatient == s.idpatient,
|
|
left_join: sr in "studyreport",
|
|
on: sr.idstudy == s.idstudy,
|
|
left_join: st in "statuses",
|
|
on: st.idstatus == sr.idstudyreport,
|
|
where: ^filter_conditions,
|
|
select: %{
|
|
recordstotal: fragment("count(*) over()"),
|
|
idstudy: fragment("substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3)", s.idstudy),
|
|
#idstudy: s.idstudy,
|
|
accessionnumber: s.accessionnumber,
|
|
studydate: s.studydate,
|
|
studytime: s.studytime,
|
|
patientname: fragment("select replace(?, '^', ' ')", p.patientname),
|
|
proceduredescription: s.studydescription,
|
|
modality: s.modality,
|
|
sitename: s.institutionname,
|
|
insurer: s.insurer,
|
|
nrodocumento: fragment("substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3)", p.patientid),
|
|
#nrodocumento: p.patientid,
|
|
hasaudio: fragment("CASE WHEN ? IS NOT NULL THEN true ELSE false END", s.audiofile)
|
|
},
|
|
order_by: ^sort_conditions,
|
|
limit: ^size,
|
|
offset: ^((page - 1) * size)
|
|
|
|
|
|
result = Repo.one(
|
|
from q in subquery(query),
|
|
group_by: q.recordstotal,
|
|
select: %{
|
|
data: fragment("json_agg(?)::text", q),
|
|
recordstotal: q.recordstotal
|
|
}
|
|
)
|
|
|
|
case result do
|
|
nil ->
|
|
%{data: [], last_page: 0}
|
|
|
|
result ->
|
|
# Calcula last_page
|
|
last_page = div(result.recordstotal + size - 1, size)
|
|
%{data: Jason.decode!(result.data), last_page: last_page}
|
|
end
|
|
|
|
end
|
|
end
|