Skip to content

Commit

Permalink
Merge pull request #269 from noharm-ai/feature/reports
Browse files Browse the repository at this point in the history
report cache test
  • Loading branch information
marceloarocha authored Nov 24, 2023
2 parents cc9dc4b + 6ba7b33 commit 4ec99e0
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 85 deletions.
4 changes: 4 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ class Config:
MAIL_PASSWORD = getenv("MAIL_PASSWORD") or "password"
MAIL_SENDER = getenv("MAIL_SENDER") or "[email protected]"
MAIL_HOST = getenv("MAIL_HOST") or "localhost"

CACHE_BUCKET_NAME = getenv("CACHE_BUCKET_NAME") or ""
CACHE_BUCKET_ID = getenv("CACHE_BUCKET_ID") or ""
CACHE_BUCKET_KEY = getenv("CACHE_BUCKET_KEY") or ""
5 changes: 5 additions & 0 deletions models/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,8 @@ class DrugTypeEnum(Enum):
SOLUTION = "Soluções"
PROCEDURE = "Proced/Exames"
DIET = "Dietas"


class ReportEnum(Enum):
RPT_BIND = "report"
RPT_GENERAL = "rpt_general"
3 changes: 2 additions & 1 deletion requirements-prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ flask-mail
random-password-generator
pyjwt[crypto]
cryptography==3.4.8
Werkzeug==2.3.7
Werkzeug==2.3.7
boto3
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ random-password-generator
pyjwt[crypto]
cryptography==3.4.8
Werkzeug==2.3.7
boto3
90 changes: 6 additions & 84 deletions routes/reports/general.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
from flask import Blueprint, request
from flask_jwt_extended import jwt_required, get_jwt_identity

Expand All @@ -7,7 +6,7 @@
from models.appendix import *
from models.segment import *
from models.prescription import *
from services import memory_service
from services.reports import general_report_service
from exception.validation_error import ValidationError

app_rpt_general = Blueprint("app_rpt_general", __name__)
Expand All @@ -19,86 +18,9 @@ def general_prescription():
user = User.find(get_jwt_identity())
dbSession.setSchema(user.schema)

cache = memory_service.get_memory("rpt_general")
try:
report_url = general_report_service.get_prescription_report(user=user)
except ValidationError as e:
return {"status": "error", "message": str(e), "code": e.code}, e.httpStatus

if cache is not None:
return {
"status": "success",
"data": cache.value,
}, status.HTTP_200_OK

sql = f"""
select
distinct on (p.fkprescricao)
p.fksetor,
p.fkprescricao,
p.convenio,
p.nratendimento,
s.nome as setorNome,
p.dtprescricao::date as data,
case
when p.status = 's' then 1
when pa.fkprescricao is not null then 1
else 0
end as checada,
case
when pa.fkprescricao is null then coalesce(array_length(p.aggmedicamento,1), 1)
else pa.total_itens
end total_itens,
case
when p.status <> 's' and pa.fkprescricao is null then 0
when pa.fkprescricao is not null then pa.total_itens
else coalesce(array_length(p.aggmedicamento,1), 1)
end total_itens_checados,
case
when p.status <> 's' and pa.fkprescricao is null then 'Não Checado'
when pa.fkprescricao is not null then user_pa.nome
else user_p.nome
end as userNome
from
{user.schema}.prescricao p
inner join {user.schema}.setor s on s.fksetor = p.fksetor
left join (
select * from {user.schema}.prescricao_audit pa where pa.tp_audit = 1
) pa on pa.fkprescricao = p.fkprescricao
left join public.usuario user_p on (p.update_by = user_p.idusuario)
left join public.usuario user_pa on pa.created_by = user_pa.idusuario
where
p.agregada = true
and p.concilia IS null
and s.fksetor in (select s2.fksetor from {user.schema}.segmentosetor s2 where s2.idsegmento is not null)
and p.dtprescricao > now() - interval '2 months'
order by p.fkprescricao, pa.created_at desc
"""

db_session = db.create_scoped_session(
options={"bind": db.get_engine(db.get_app(), "report")}
)

results = db_session.execute(sql).fetchall()
itens = []
for i in results:
itens.append(
{
"idDepartment": i[0],
"idPrescription": i[1],
"insurance": i[2],
"admissionNumber": i[3],
"department": i[4],
"date": i[5].isoformat(),
"checked": i[6],
"itens": i[7],
"checkedItens": i[8],
"responsible": i[9],
}
)

memory_service.save_unique_memory("rpt_general", itens, user)

return tryCommit(
db,
{
"status": "success",
"data": itens,
},
)
return tryCommit(db, {"url": report_url})
47 changes: 47 additions & 0 deletions services/reports/cache_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import boto3
import json
import io
import gzip

from config import Config


def _get_client():
return boto3.client(
"s3",
aws_access_key_id=Config.CACHE_BUCKET_ID,
aws_secret_access_key=Config.CACHE_BUCKET_KEY,
)


def get_resource_name(cache_id, report, schema):
return f"{schema}_{cache_id}_{report}.gz"


def generate_link(cache_id, report, schema):
client = _get_client()

return client.generate_presigned_url(
"get_object",
Params={
"Bucket": Config.CACHE_BUCKET_NAME,
"Key": get_resource_name(cache_id, report, schema),
},
ExpiresIn=100,
)


def save_cache(cache_id, report, schema, data):
client = _get_client()

file = io.BytesIO()
with gzip.GzipFile(fileobj=file, mode="wb") as fh:
with io.TextIOWrapper(fh, encoding="utf-8") as wrapper:
wrapper.write(json.dumps(data, ensure_ascii=False))
file.seek(0)

client.put_object(
Body=file,
Bucket=Config.CACHE_BUCKET_NAME,
Key=get_resource_name(cache_id, report, schema),
)
108 changes: 108 additions & 0 deletions services/reports/general_report_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from sqlalchemy import func
from datetime import date

from models.main import *
from models.appendix import *
from models.segment import *
from models.enums import ReportEnum
from services import memory_service
from services.reports import cache_service


def get_prescription_report(user):
cache_data = (
db.session.query(Memory)
.filter(Memory.kind == ReportEnum.RPT_GENERAL.value)
.filter(func.date(Memory.update) == date.today())
.first()
)

if cache_data != None:
return cache_service.generate_link(
cache_data.key, ReportEnum.RPT_GENERAL.value, user.schema
)

list = _get_prescription_list(user)

cache = memory_service.save_unique_memory(ReportEnum.RPT_GENERAL.value, {}, user)

cache_service.save_cache(
cache_id=cache.key,
report=ReportEnum.RPT_GENERAL.value,
schema=user.schema,
data=list,
)

return cache_service.generate_link(
cache.key, ReportEnum.RPT_GENERAL.value, user.schema
)


def _get_prescription_list(user):
sql = f"""
select
distinct on (p.fkprescricao)
p.fksetor,
p.fkprescricao,
p.convenio,
p.nratendimento,
s.nome as setorNome,
p.dtprescricao::date as data,
case
when p.status = 's' then 1
when pa.fkprescricao is not null then 1
else 0
end as checada,
case
when pa.fkprescricao is null then coalesce(array_length(p.aggmedicamento,1), 1)
else pa.total_itens
end total_itens,
case
when p.status <> 's' and pa.fkprescricao is null then 0
when pa.fkprescricao is not null then pa.total_itens
else coalesce(array_length(p.aggmedicamento,1), 1)
end total_itens_checados,
case
when p.status <> 's' and pa.fkprescricao is null then 'Não Checado'
when pa.fkprescricao is not null then user_pa.nome
else user_p.nome
end as userNome
from
{user.schema}.prescricao p
inner join {user.schema}.setor s on s.fksetor = p.fksetor
left join (
select * from {user.schema}.prescricao_audit pa where pa.tp_audit = 1
) pa on pa.fkprescricao = p.fkprescricao
left join public.usuario user_p on (p.update_by = user_p.idusuario)
left join public.usuario user_pa on pa.created_by = user_pa.idusuario
where
p.agregada = true
and p.concilia IS null
and s.fksetor in (select s2.fksetor from {user.schema}.segmentosetor s2 where s2.idsegmento is not null)
and p.dtprescricao > now() - interval '2 months'
order by p.fkprescricao, pa.created_at desc
"""

db_session = db.create_scoped_session(
options={"bind": db.get_engine(db.get_app(), ReportEnum.RPT_BIND.value)}
)

results = db_session.execute(sql).fetchall()
itens = []
for i in results:
itens.append(
{
"idDepartment": i[0],
"idPrescription": i[1],
"insurance": i[2],
"admissionNumber": i[3],
"department": i[4],
"date": i[5].isoformat(),
"checked": i[6],
"itens": i[7],
"checkedItens": i[8],
"responsible": i[9],
}
)

return itens

0 comments on commit 4ec99e0

Please sign in to comment.