Subiendo api v2
This commit is contained in:
70
lib/api/api_consultas/downloadpdf.ex
Normal file
70
lib/api/api_consultas/downloadpdf.ex
Normal file
@ -0,0 +1,70 @@
|
||||
defmodule Api.Downloadpdf do
|
||||
import Ecto.Query
|
||||
alias Api.Repo
|
||||
require Logger
|
||||
|
||||
def get_report_query(idstudyreport) do
|
||||
Logger.info("hash antes de query: #{idstudyreport}")
|
||||
# uso hex en la desencriptación porque el proceso de encriptación involucraba convertir los datos binarios a una cadena de texto (substring)
|
||||
q = """
|
||||
SELECT convert_from(decrypt(decode('#{idstudyreport}', 'hex')::bytea, '1nf0rm3'::bytea, 'aes'), 'UTF8');
|
||||
"""
|
||||
idstudyreport = Repo.query!(q).rows |> hd() |> hd()
|
||||
Logger.info("hash despues de query: #{idstudyreport}")
|
||||
|
||||
idstudyreport = String.to_integer(idstudyreport)
|
||||
|
||||
template_name = Envar.get("TEMPLATE_NAME")
|
||||
# template_name = System.get_env("TEMPLATE_NAME")
|
||||
Logger.info("template: #{template_name}")
|
||||
# pr2_statusname = Envar.get("pr2_statusname")
|
||||
|
||||
query =
|
||||
from sr in "studyreport",
|
||||
join: s in "study",
|
||||
on: s.idstudy == sr.idstudy,
|
||||
join: p in "patient",
|
||||
on: p.idpatient == s.idpatient,
|
||||
left_join: pr in "professional",
|
||||
on: pr.idprofessional == sr.idprofessional_finalizedby,
|
||||
left_join: u in "users",
|
||||
on: u.iduser == pr.iduser,
|
||||
join: pt in "printtemplates",
|
||||
on: pt.printtemplate_type == "STUDYREPORT",
|
||||
where: sr.idstudyreport == ^idstudyreport,
|
||||
where: pt.printtemplate == ^template_name,
|
||||
where: pt.enabled == true,
|
||||
select: %{
|
||||
idstudyreport: sr.idstudyreport,
|
||||
body: sr.body,
|
||||
idstudy: s.idstudy,
|
||||
printtemplate: pt.template,
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientname: fragment("replace(?, '^', ' ')", p.patientname),
|
||||
studydate: fragment("TO_CHAR(?, 'YYYY-MM-DD')", s.studydate),
|
||||
studytime: s.studytime,
|
||||
studydescription: s.studydescription,
|
||||
proceduredescription: s.proceduredescription,
|
||||
procedurecode: s.procedurecode,
|
||||
modality: s.modality,
|
||||
patientid: p.patientid,
|
||||
patientbirthdate: fragment("TO_CHAR(?, 'YYYY-MM-DD')", p.patientbirthdate),
|
||||
fin_signature: pr.signature,
|
||||
matricula_finalized: fragment("COALESCE(?, '')",pr.matricula),
|
||||
informantphysician: u.username,
|
||||
insurer: fragment("COALESCE(?, '')",s.insurer),
|
||||
institutionname: s.institutionname,
|
||||
referringphysiciansname: fragment("COALESCE(?, '')", s.referringphysiciansname)
|
||||
}
|
||||
|
||||
|
||||
result = Repo.one(
|
||||
from q in subquery(query),
|
||||
select: fragment("json_build_object('idstudyreport', ?, 'body', ?, 'idstudy', ?, 'accessionnumber', ?, 'patientname', ?, 'studydate', ?, 'studytime', ?, 'studydescription', ?, 'proceduredescription', ?, 'procedurecode', ?, 'modality', ?, 'patientid', ?, 'patientbirthdate', ?, 'fin_signature', ?, 'matricula_finalized', ?, 'informantphysician', ?, 'insurer', ?, 'institutionname', ?, 'referringphysiciansname', ?, 'printtemplate', ?)",
|
||||
q.idstudyreport, q.body, q.idstudy, q.accessionnumber, q.patientname, q.studydate, q.studytime, q.studydescription, q.proceduredescription, q.procedurecode, q.modality, q.patientid, q.patientbirthdate, q.fin_signature, q.matricula_finalized, q.informantphysician, q.insurer, q.institutionname, q.referringphysiciansname, q.printtemplate
|
||||
)
|
||||
)
|
||||
Logger.info("#{inspect(result)}")
|
||||
result
|
||||
end
|
||||
end
|
||||
136
lib/api/api_consultas/studies.ex
Normal file
136
lib/api/api_consultas/studies.ex
Normal file
@ -0,0 +1,136 @@
|
||||
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
|
||||
153
lib/api/api_consultas/study.ex
Normal file
153
lib/api/api_consultas/study.ex
Normal file
@ -0,0 +1,153 @@
|
||||
defmodule Api.Study do
|
||||
import Ecto.Query
|
||||
alias Api.Repo
|
||||
require Logger
|
||||
|
||||
def open_study(accession) do
|
||||
Envar.load(".env")
|
||||
Envar.require_env_file(".env")
|
||||
|
||||
idsite = Envar.get("IDSITE") |> String.to_integer
|
||||
domain = Envar.get("CHECK_ORIGIN")
|
||||
escaneados = Envar.get("ESCANEADOS")
|
||||
|
||||
id_study = if Envar.get("IDENTIFIERFIELD") == "ACCESSIONNUMBER" do
|
||||
query =
|
||||
from s in "study",
|
||||
where: s.accessionnumber == ^accession,
|
||||
select: s.idstudy
|
||||
idstudy = Repo.one(query)
|
||||
Logger.info("accession ----> #{inspect(accession)} - idstudy -------> #{inspect(idstudy)}")
|
||||
idstudy
|
||||
else
|
||||
accession
|
||||
end
|
||||
|
||||
# id_study = if is_integer(id_study), do: id_study, else: String.to_integer(id_study)
|
||||
|
||||
|
||||
# accession_fragment =
|
||||
# if Envar.get("IDENTIFIERFIELD") == "ACCESSIONNUMBER" do
|
||||
# fragment("?::text", ^accession)
|
||||
# else
|
||||
# fragment("?::integer", ^id_study)
|
||||
# end
|
||||
|
||||
|
||||
Logger.info("id_study -------> #{inspect(id_study)}")
|
||||
|
||||
# Las siguientes consultas obtienen la información completa
|
||||
# de un estudio.
|
||||
|
||||
# informes
|
||||
subquery1 = subquery(
|
||||
from s in "study",
|
||||
join: sr in "studyreport", on: sr.idstudy == s.idstudy,
|
||||
join: p in "patient", on: s.idpatient == p.idpatient,
|
||||
where: not is_nil(sr.body) and s.idstudy == ^id_study and
|
||||
sr.idstatus in subquery(
|
||||
from st in "statuses",
|
||||
where: st.statusname in ["Revisado", "Final"],
|
||||
select: st.idstatus
|
||||
),
|
||||
select: %{
|
||||
idsite: type(^idsite, :integer),
|
||||
iddocument: fragment("substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3)", sr.idstudyreport),
|
||||
document_name: "INFORME PRINCIPAL",
|
||||
document_type: "pdf",
|
||||
url: fragment(
|
||||
"concat(?::text, ?::text, substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3))",
|
||||
^domain,
|
||||
"/api/downloadpdf/",
|
||||
sr.idstudyreport
|
||||
),
|
||||
patientname: p.patientname,
|
||||
proceduredescription: s.studydescription,
|
||||
studydate: fragment("TO_CHAR(?, 'YYYY-MM-DD')", s.studydate),
|
||||
studytime: fragment("TO_CHAR(?, 'HH24:MI:SS')", s.studytime),
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientid: p.patientid
|
||||
}
|
||||
)
|
||||
|
||||
# escaneados
|
||||
subquery2 = subquery(
|
||||
from s in "study",
|
||||
join: ss in "studyscans", on: ss.idstudy == s.idstudy,
|
||||
join: sc in "scanclasses", on: sc.idscanclass == ss.idscanclass,
|
||||
join: p in "patient", on: s.idpatient == p.idpatient,
|
||||
where: s.idstudy == ^id_study,
|
||||
select: %{
|
||||
idsite: type(^idsite, :integer),
|
||||
iddocument: fragment("substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3)", ss.idstudyscan),
|
||||
document_name: sc.scanclass,
|
||||
document_type: "url",
|
||||
url: fragment(
|
||||
"concat(?::text, substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3))",
|
||||
^escaneados,
|
||||
ss.idstudyscan
|
||||
),
|
||||
patientname: p.patientname,
|
||||
proceduredescription: s.studydescription,
|
||||
studydate: fragment("TO_CHAR(?, 'YYYY-MM-DD')", s.studydate),
|
||||
studytime: fragment("TO_CHAR(?, 'HH24:MI:SS')", s.studytime),
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientid: p.patientid
|
||||
}
|
||||
)
|
||||
|
||||
# adjuntos
|
||||
subquery3 =
|
||||
from s in "study",
|
||||
join: sa in "studyattachments", on: sa.idstudy == s.idstudy,
|
||||
join: p in "patient", on: p.idpatient == s.idpatient,
|
||||
where: s.idstudy == ^id_study,
|
||||
select: %{
|
||||
idsite: type(^idsite, :integer),
|
||||
iddocument: fragment("substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3)", sa.idstudyattachment),
|
||||
document_name: sa.name,
|
||||
document_type: fragment("CASE WHEN ? NOT IN ('jpg', 'jpeg', 'png') THEN 'attachment' ELSE 'url' END", sa.format),
|
||||
url: fragment(
|
||||
"concat(?::text, ?::text, substring(encrypt(?::text::bytea, '1nf0rm3', 'aes')::text from 3))",
|
||||
^domain,
|
||||
"/api/attachment/",
|
||||
sa.idstudyattachment
|
||||
),
|
||||
patientname: p.patientname,
|
||||
proceduredescription: s.studydescription,
|
||||
studydate: fragment("TO_CHAR(?, 'YYYY-MM-DD')", s.studydate),
|
||||
studytime: fragment("TO_CHAR(?, 'HH24:MI:SS')", s.studytime),
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientid: ""
|
||||
}
|
||||
|
||||
# Si no encontró informes, ni adjuntos, ni nada
|
||||
# se traen sólo los datos básicos del estudio
|
||||
basicquery =
|
||||
from s in "study",
|
||||
join: p in "patient", on: p.idpatient == s.idpatient,
|
||||
where: s.idstudy == ^id_study,
|
||||
select: %{
|
||||
idsite: type(^idsite, :integer),
|
||||
patientname: p.patientname,
|
||||
proceduredescription: s.studydescription,
|
||||
studydate: fragment("TO_CHAR(?, 'YYYY-MM-DD')", s.studydate),
|
||||
studytime: fragment("TO_CHAR(?, 'HH24:MI:SS')", s.studytime),
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientid: ""
|
||||
}
|
||||
|
||||
|
||||
combined_query =
|
||||
from q in subquery1,
|
||||
union_all: ^subquery2,
|
||||
union_all: ^subquery3,
|
||||
select: q
|
||||
|
||||
results = Repo.all(combined_query)
|
||||
case results do
|
||||
[] -> Repo.all(from q in basicquery)
|
||||
_ -> results
|
||||
end
|
||||
end
|
||||
end
|
||||
37
lib/api/application.ex
Normal file
37
lib/api/application.ex
Normal file
@ -0,0 +1,37 @@
|
||||
defmodule Api.Application do
|
||||
# See https://hexdocs.pm/elixir/Application.html
|
||||
# for more information on OTP Applications
|
||||
@moduledoc false
|
||||
|
||||
use Application
|
||||
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
children = [
|
||||
ApiWeb.Telemetry,
|
||||
Api.Repo,
|
||||
#{Api.Autosender, 1000 * 62 * 4},
|
||||
# {DNSCluster, query: Application.get_env(:api, :dns_cluster_query) || :ignore},
|
||||
{Phoenix.PubSub, name: Api.PubSub},
|
||||
# Start the Finch HTTP client for sending emails
|
||||
{Finch, name: Api.Finch},
|
||||
# Start a worker by calling: Api.Worker.start_link(arg)
|
||||
# {Api.Worker, arg},
|
||||
# Start to serve requests, typically the last entry
|
||||
ApiWeb.Endpoint
|
||||
]
|
||||
|
||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
# for other strategies and supported options
|
||||
opts = [strategy: :one_for_one, name: Api.Supervisor]
|
||||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
|
||||
# Tell Phoenix to update the endpoint configuration
|
||||
# whenever the application is updated.
|
||||
@impl true
|
||||
def config_change(changed, _new, removed) do
|
||||
ApiWeb.Endpoint.config_change(changed, removed)
|
||||
:ok
|
||||
end
|
||||
end
|
||||
26
lib/api/emailsender/autosender.ex
Normal file
26
lib/api/emailsender/autosender.ex
Normal file
@ -0,0 +1,26 @@
|
||||
defmodule Api.Autosender do
|
||||
|
||||
alias Api.StudyMailer
|
||||
use GenServer
|
||||
|
||||
def start_link(period_in_millis) do
|
||||
GenServer.start_link(__MODULE__, %{period: period_in_millis})
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(state) do
|
||||
next_send(state.period)
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
def next_send(period_in_millis) do
|
||||
Process.send_after(self(), :send, period_in_millis)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:send, state) do
|
||||
StudyMailer.deliver_mail()
|
||||
next_send(state.period)
|
||||
{:noreply, state}
|
||||
end
|
||||
end
|
||||
179
lib/api/emailsender/contexts/emailstosendcontext.ex
Normal file
179
lib/api/emailsender/contexts/emailstosendcontext.ex
Normal file
@ -0,0 +1,179 @@
|
||||
defmodule Api.EmailToSendContext do
|
||||
|
||||
require Logger
|
||||
import Ecto.Query, warn: false
|
||||
alias Api.Repo
|
||||
alias Api.Emailtosend
|
||||
alias Api.Pagination
|
||||
|
||||
|
||||
def mark_sent(idemailtosend, attrs)do
|
||||
from(e in Emailtosend, where: e.idemailtosend == ^idemailtosend)
|
||||
|> Repo.one
|
||||
|> Emailtosend.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
defp list_emails({filter, sort}) do
|
||||
filter_conditions =
|
||||
Enum.reduce(filter, true, fn v, filter_conditions ->
|
||||
case v["field"] do
|
||||
"idstudy" ->
|
||||
dynamic([e], e.idstudy == ^v["value"] and ^filter_conditions)
|
||||
|
||||
"patientemail" ->
|
||||
dynamic([e], ilike(e.patientemail, ^"#{v["value"]}%") and ^filter_conditions)
|
||||
|
||||
"sent" ->
|
||||
dynamic([e], e.sent == ^v["value"] and ^filter_conditions)
|
||||
|
||||
"hasreport" ->
|
||||
dynamic([e], e.hasreport == ^v["value"] and ^filter_conditions)
|
||||
|
||||
"retries" ->
|
||||
dynamic([e], e.retries == ^v["value"] and ^filter_conditions)
|
||||
|
||||
"errormsg" ->
|
||||
dynamic([e], ilike(e.errormsg, ^"#{v["value"]}%") and ^filter_conditions)
|
||||
|
||||
"forcereprocess" ->
|
||||
dynamic([e], e.send == ^v["forcereprocess"] and ^filter_conditions)
|
||||
|
||||
"sentdatetime" ->
|
||||
dynamic([e], e.send == ^v["sentdatetime"] and ^filter_conditions)
|
||||
|
||||
"accessionnumber" ->
|
||||
dynamic([s], ilike(s.accessionnumber, ^"#{v["value"]}%") and ^filter_conditions)
|
||||
|
||||
"errormsg" ->
|
||||
dynamic([p], ilike(p.patientname, ^"#{v["value"]}%") and ^filter_conditions)
|
||||
|
||||
"errormsg" ->
|
||||
dynamic([p], ilike(p.patientid, ^"#{v["value"]}%") and ^filter_conditions)
|
||||
|
||||
"errormsg" ->
|
||||
dynamic([s], ilike(s.studydate, ^"#{v["value"]}%") and ^filter_conditions)
|
||||
|
||||
_ ->
|
||||
filter_conditions
|
||||
end
|
||||
end)
|
||||
|
||||
sort_values =
|
||||
case sort do
|
||||
[] -> [desc: :idstudy]
|
||||
_ -> Enum.reduce(sort, [], fn v, acc ->
|
||||
IO.inspect(v)
|
||||
case v["field"] do
|
||||
"patientname" ->
|
||||
if v["dir"] == "asc" do
|
||||
[asc: dynamic([_,_,p], p.patientname)]
|
||||
else
|
||||
[desc: dynamic([_,_,p], p.patientname)]
|
||||
end
|
||||
"patientid" ->
|
||||
if v["dir"] == "asc" do
|
||||
[asc: dynamic([_,_,p], p.patientid)]
|
||||
else
|
||||
[desc: dynamic([_,_,p], p.patientid)]
|
||||
end
|
||||
"accessionnumber" ->
|
||||
if v["dir"] == "asc" do
|
||||
[asc: dynamic([_,s], s.accessionnumber)]
|
||||
else
|
||||
[desc: dynamic([_,s], s.accessionnumber)]
|
||||
end
|
||||
"studydate" ->
|
||||
if v["dir"] == "asc" do
|
||||
[asc: dynamic([_,s], s.studydate)]
|
||||
else
|
||||
[desc: dynamic([_,s], s.studydate)]
|
||||
end
|
||||
_ ->
|
||||
if v["dir"] == "asc" do
|
||||
Enum.concat( acc, asc: String.to_existing_atom(v["field"]))
|
||||
else
|
||||
Enum.concat( acc, desc: String.to_existing_atom(v["field"]))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
queryable = from(
|
||||
e in Emailtosend,
|
||||
where: ^filter_conditions,
|
||||
join: s in "study", on: s.idstudy == e.idstudy,
|
||||
join: p in "patient", on: p.idpatient == s.idpatient,
|
||||
order_by: ^sort_values,
|
||||
select: %{
|
||||
idemailtosend: e.idemailtosend,
|
||||
idstudy: e.idstudy,
|
||||
patientemail: e.patientemail,
|
||||
sent: e.sent,
|
||||
hasreport: e.hasreport,
|
||||
retries: e.retries,
|
||||
errormsg: e.errormsg,
|
||||
forcereprocess: e.forcereprocess,
|
||||
sentdatetime: e.sentdatetime,
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientname: p.patientname,
|
||||
patientid: p.patientid,
|
||||
studydate: s.studydate
|
||||
}
|
||||
)
|
||||
|
||||
queryable
|
||||
end
|
||||
|
||||
def list_emails(:paged, params, page, per_page) do
|
||||
list_emails(params)
|
||||
|> Pagination.page(page, per_page: per_page)
|
||||
end
|
||||
|
||||
def get_email_by_id(id) do
|
||||
from(e in Emailtosend, where: e.idemailtosend == ^id)
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
def update_emailtosend(attrs) do
|
||||
get_email_by_id(attrs["idemailtosend"])
|
||||
|> Emailtosend.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
def get_next_email() do
|
||||
from(
|
||||
e in Emailtosend,
|
||||
join: s in "study", on: s.idstudy == e.idstudy,
|
||||
join: p in "patient", on: p.idpatient == s.idpatient,
|
||||
where:
|
||||
(
|
||||
e.patientemail != "notiene@notiene.com" and
|
||||
e.patientemail != "" and
|
||||
not is_nil(e.patientemail) and
|
||||
e.forcereprocess == true
|
||||
) or
|
||||
(
|
||||
e.patientemail != "notiene@notiene.com" and
|
||||
e.patientemail != "" and
|
||||
not is_nil(e.patientemail) and
|
||||
e.hasreport == true and
|
||||
e.sent != true and
|
||||
e.retries < 10
|
||||
),
|
||||
limit: 1,
|
||||
select: %{
|
||||
idemailtosend: e.idemailtosend,
|
||||
retries: e.retries,
|
||||
idstudy: s.idstudy,
|
||||
accessionnumber: s.accessionnumber,
|
||||
patientemail: e.patientemail,
|
||||
patientname: p.patientname,
|
||||
patientid: p.patientid,
|
||||
studydate: s.studydate
|
||||
}
|
||||
)
|
||||
|> Repo.one()
|
||||
|> IO.inspect(label: "CONTEXTO")
|
||||
end
|
||||
|
||||
end
|
||||
30
lib/api/emailsender/schemas/Emailstosend.ex
Normal file
30
lib/api/emailsender/schemas/Emailstosend.ex
Normal file
@ -0,0 +1,30 @@
|
||||
defmodule Api.Emailtosend do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@derive {Jason.Encoder, only: [:idemailtosend, :idstudy, :patientemail, :sent, :hasreport, :retries, :errormsg, :forcereprocess, :sentdatetime]}
|
||||
@primary_key {:idemailtosend, :id, autogenerate: true}
|
||||
schema "emailstosend" do
|
||||
field :idstudy, :integer
|
||||
field :patientemail, :string
|
||||
field :sent, :boolean
|
||||
field :hasreport, :boolean
|
||||
field :retries, :integer
|
||||
field :errormsg, :string
|
||||
field :forcereprocess, :boolean
|
||||
field :sentdatetime, :naive_datetime
|
||||
end
|
||||
|
||||
def changeset(emailtosend, attrs) do
|
||||
emailtosend
|
||||
|> cast(attrs, [:idstudy,
|
||||
:patientemail,
|
||||
:sent,
|
||||
:hasreport,
|
||||
:retries,
|
||||
:errormsg,
|
||||
:forcereprocess,
|
||||
:sentdatetime])
|
||||
|> validate_required([])
|
||||
end
|
||||
end
|
||||
56
lib/api/emailsender/studymailer.ex
Normal file
56
lib/api/emailsender/studymailer.ex
Normal file
@ -0,0 +1,56 @@
|
||||
defmodule Api.StudyMailer do
|
||||
import Swoosh.Email
|
||||
alias Api.EmailToSendContext
|
||||
alias Api.Mailer
|
||||
|
||||
def create_mail(mail) do
|
||||
|
||||
|
||||
Envar.load(".env")
|
||||
Envar.require_env_file(".env")
|
||||
htmlbody = File.read(Envar.get("EMAIL_BODY_PATH"))
|
||||
|> elem(1)
|
||||
|> Solid.parse()
|
||||
|> elem(1)
|
||||
|> Solid.render!(
|
||||
%{"mail" =>
|
||||
%{"patientname" => mail.patientname |> String.replace("^", " "),
|
||||
"studydate" => mail.studydate,
|
||||
"patientid" => mail.patientid,
|
||||
"accessionnumber" => mail.accessionnumber,
|
||||
"idstudy" => mail.idstudy}
|
||||
})
|
||||
|> to_string()
|
||||
new()
|
||||
|> to({mail.patientname |> String.replace("^", " "), mail.patientemail |> String.trim |> String.replace(" ", "")})
|
||||
|> from({Envar.get("FROM"), Envar.get("SMTP_USER")})
|
||||
|> subject("Resultado del estudio")
|
||||
|> html_body(htmlbody)
|
||||
|
||||
end
|
||||
|
||||
def deliver_mail() do
|
||||
email = EmailToSendContext.get_next_email()
|
||||
if email do
|
||||
email_regex = ~r/[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n]+/
|
||||
if String.match?(email.patientemail, email_regex) do
|
||||
emailtosendtest = create_mail(email)
|
||||
{res, term} = Mailer.deliver(emailtosendtest)
|
||||
case res do
|
||||
:ok ->
|
||||
EmailToSendContext.mark_sent(email.idemailtosend, %{sent: true, forcereprocess: false})
|
||||
:error ->
|
||||
EmailToSendContext.mark_sent(email.idemailtosend, %{errormsg: "Error", retries: email.retries + 1, forcereprocess: false})
|
||||
IO.inspect(res, label: "===> ERROR ======>")
|
||||
IO.inspect(term, label: "===> ERROR ======>")
|
||||
_ ->
|
||||
IO.inspect(res)
|
||||
end
|
||||
else
|
||||
EmailToSendContext.mark_sent(email.idemailtosend, %{errormsg: "Mail Incorrecto", retries: 10, forcereprocess: false})
|
||||
end
|
||||
else
|
||||
IO.puts("No hay estudios para enviar. Revisar que los mismos tengan un informe y mail correcto")
|
||||
end
|
||||
end
|
||||
end
|
||||
4
lib/api/mailer.ex
Normal file
4
lib/api/mailer.ex
Normal file
@ -0,0 +1,4 @@
|
||||
defmodule Api.Mailer do
|
||||
use Swoosh.Mailer, otp_app: :api,
|
||||
adapter: Swoosh.Adapters.SMTP
|
||||
end
|
||||
39
lib/api/pagination.ex
Normal file
39
lib/api/pagination.ex
Normal file
@ -0,0 +1,39 @@
|
||||
defmodule Api.Pagination do
|
||||
import Ecto.Query
|
||||
|
||||
alias Api.Repo
|
||||
|
||||
def query(query, page, per_page: per_page) when is_binary(page) do
|
||||
query(query, String.to_integer(page), per_page: per_page)
|
||||
end
|
||||
|
||||
def query(query, page, per_page: per_page) do
|
||||
query
|
||||
|> limit(^(per_page + 1))
|
||||
|> offset(^(per_page * (page - 1)))
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def page(query, page, per_page: per_page) when is_binary(page) do
|
||||
page(query, String.to_integer(page), per_page: per_page)
|
||||
end
|
||||
|
||||
def page(query, page, per_page: per_page) do
|
||||
results = query(query, page, per_page: per_page)
|
||||
has_next = length(results) > per_page
|
||||
has_previous = page > 1
|
||||
count = Repo.one(from(t in subquery(query), select: count("*")))
|
||||
%{
|
||||
has_next: has_next,
|
||||
has_previous: has_previous,
|
||||
prev_page: page - 1,
|
||||
page: page,
|
||||
next_page: page + 1,
|
||||
first: (page - 1) * per_page + 1,
|
||||
last: Enum.min([page * per_page, count]),
|
||||
# total de registros
|
||||
total_pages: round(count / per_page),
|
||||
list: Enum.slice(results, 0, per_page)
|
||||
}
|
||||
end
|
||||
end
|
||||
28
lib/api/release.ex
Normal file
28
lib/api/release.ex
Normal file
@ -0,0 +1,28 @@
|
||||
defmodule Api.Release do
|
||||
@moduledoc """
|
||||
Used for executing DB release tasks when run in production without Mix
|
||||
installed.
|
||||
"""
|
||||
@app :api
|
||||
|
||||
def migrate do
|
||||
load_app()
|
||||
|
||||
for repo <- repos() do
|
||||
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
|
||||
end
|
||||
end
|
||||
|
||||
def rollback(repo, version) do
|
||||
load_app()
|
||||
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
|
||||
end
|
||||
|
||||
defp repos do
|
||||
Application.fetch_env!(@app, :ecto_repos)
|
||||
end
|
||||
|
||||
defp load_app do
|
||||
Application.load(@app)
|
||||
end
|
||||
end
|
||||
5
lib/api/repo.ex
Normal file
5
lib/api/repo.ex
Normal file
@ -0,0 +1,5 @@
|
||||
defmodule Api.Repo do
|
||||
use Ecto.Repo,
|
||||
otp_app: :api,
|
||||
adapter: Ecto.Adapters.Postgres
|
||||
end
|
||||
Reference in New Issue
Block a user