This commit is contained in:
@@ -0,0 +1,475 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Mobile\ConectaCidadao\Farmacia;
|
||||
|
||||
use App\Enums\Geral\MedidaTempo;
|
||||
use App\Enums\Mobile\ConectaCidadao\Farmacia\MonitoramentoPosologia;
|
||||
use App\Models\Farmacia\AppCidadaoLog;
|
||||
use App\Models\Farmacia\ParametrizacaoAppCidadao;
|
||||
use App\Models\Farmacia\ReceitaItem;
|
||||
use App\Models\Farmacia\ReceitaMonitoramentoPosologia;
|
||||
use App\Models\Farmacia\ReceitaTratamentoInicio;
|
||||
use App\Services\Service;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class MonitoramentoPosologiaService extends Service
|
||||
{
|
||||
public static function medicamentos(): array
|
||||
{
|
||||
self::verificarParametrizacao();
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$rows = DB::table('farmacia_receita_item as fri')
|
||||
->select(
|
||||
'fri.id as item_id',
|
||||
'fr.id as receita_id',
|
||||
'fr.data_receita',
|
||||
'cm.descricao as material_descricao',
|
||||
'um.nome as unidade_medida_nome',
|
||||
'fri.quantidade',
|
||||
'fri.intervalo_tempo',
|
||||
'fri.intervalo_medida_tempo_id',
|
||||
'mt.nome as intervalo_medida_tempo_nome',
|
||||
'fri.durante_tempo',
|
||||
'ti.inicio_em',
|
||||
'ti.interrompido_em',
|
||||
DB::raw("(SELECT COUNT(*) FROM farmacia_receita_monitoramento_posologia WHERE receita_item_id = fri.id AND paciente_id = {$pacienteId}) as total_confirmadas")
|
||||
)
|
||||
->join('farmacia_receita as fr', 'fr.id', 'fri.receita_id')
|
||||
->join('cadastro_material as cm', 'cm.id', 'fri.material_id')
|
||||
->leftJoin('cadastro_unidade_medida as um', 'um.id', 'cm.apresentacao_unidade_medida_id')
|
||||
->leftJoin('geral_medida_tempo as mt', 'mt.id', 'fri.intervalo_medida_tempo_id')
|
||||
->leftJoin('farmacia_receita_tratamento_inicio as ti', function ($join) use ($pacienteId) {
|
||||
$join->on('ti.receita_item_id', '=', 'fri.id')
|
||||
->where('ti.paciente_id', '=', $pacienteId);
|
||||
})
|
||||
->where('fr.paciente_id', $pacienteId)
|
||||
->where(function ($q) {
|
||||
$q->whereDate('fri.proxima_retirada', '>=', now()->toDateString())
|
||||
->orWhereNotNull('ti.inicio_em');
|
||||
})
|
||||
->orderBy('fr.data_receita', 'desc')
|
||||
->orderBy('fri.id', 'asc')
|
||||
->get();
|
||||
|
||||
$receitas = [];
|
||||
|
||||
foreach ($rows as $row) {
|
||||
|
||||
$receitaId = $row->receita_id;
|
||||
|
||||
if (!isset($receitas[$receitaId])) {
|
||||
|
||||
$receitas[$receitaId] = [
|
||||
'id' => $receitaId,
|
||||
'data_receita' => $row->data_receita,
|
||||
'itens' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$inicioEm = $row->inicio_em ? Carbon::parse($row->inicio_em) : null;
|
||||
$interrompidoEm = $row->interrompido_em ? Carbon::parse($row->interrompido_em) : null;
|
||||
|
||||
$receitas[$receitaId]['itens'][] = [
|
||||
'id' => $row->item_id,
|
||||
'medicamento' => $row->material_descricao,
|
||||
'posologia_texto' => self::montarPosologiaTexto($row),
|
||||
'posologia_incompleta' => is_null($row->intervalo_tempo) || is_null($row->durante_tempo),
|
||||
'status' => self::calcularStatus(
|
||||
$row->durante_tempo,
|
||||
$row->intervalo_tempo,
|
||||
$row->intervalo_medida_tempo_id,
|
||||
$inicioEm,
|
||||
$interrompidoEm,
|
||||
(int) $row->total_confirmadas
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'habilitado' => true,
|
||||
'data' => array_values($receitas),
|
||||
];
|
||||
}
|
||||
|
||||
public static function iniciar(int $receitaItemId): array
|
||||
{
|
||||
self::verificarParametrizacao();
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$item = ReceitaItem::findOrFail($receitaItemId);
|
||||
abort_if($item->receita->paciente_id !== $pacienteId, Response::HTTP_FORBIDDEN);
|
||||
|
||||
request()->validate([
|
||||
'inicio_em' => ['required', 'date'],
|
||||
'aderiu_tratamento' => ['nullable', 'boolean'],
|
||||
]);
|
||||
|
||||
$inicioEm = Carbon::parse(request()->input('inicio_em'));
|
||||
|
||||
ReceitaTratamentoInicio::updateOrCreate(
|
||||
['receita_item_id' => $receitaItemId, 'paciente_id' => $pacienteId],
|
||||
[
|
||||
'inicio_em' => $inicioEm,
|
||||
'interrompido_em' => null,
|
||||
'aderiu_tratamento' => request()->boolean('aderiu_tratamento'),
|
||||
]
|
||||
);
|
||||
|
||||
if ($inicioEm->isPast()) {
|
||||
|
||||
ReceitaMonitoramentoPosologia::firstOrCreate(
|
||||
['receita_item_id' => $receitaItemId, 'paciente_id' => $pacienteId, 'dose_numero' => 1],
|
||||
['confirmado_em' => $inicioEm, 'observacao' => null]
|
||||
);
|
||||
}
|
||||
|
||||
self::log($pacienteId, 'INICIO_TRATAMENTO', $item->receita_id, $receitaItemId);
|
||||
|
||||
return ['registrado' => true];
|
||||
}
|
||||
|
||||
public static function index(int $receitaItemId): array
|
||||
{
|
||||
self::verificarParametrizacao();
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$item = ReceitaItem::findOrFail($receitaItemId);
|
||||
abort_if($item->receita->paciente_id !== $pacienteId, Response::HTTP_FORBIDDEN);
|
||||
|
||||
$inicio = ReceitaTratamentoInicio::where('receita_item_id', $receitaItemId)
|
||||
->where('paciente_id', $pacienteId)
|
||||
->first();
|
||||
|
||||
$confirmacoes = ReceitaMonitoramentoPosologia::where('receita_item_id', $receitaItemId)
|
||||
->where('paciente_id', $pacienteId)
|
||||
->orderBy('dose_numero')
|
||||
->get();
|
||||
|
||||
$inicioEm = $inicio ? $inicio->inicio_em : null;
|
||||
$interrompidoEm = $inicio ? $inicio->interrompido_em : null;
|
||||
|
||||
$status = self::calcularStatus(
|
||||
$item->durante_tempo,
|
||||
$item->intervalo_tempo,
|
||||
$item->intervalo_medida_tempo_id,
|
||||
$inicioEm,
|
||||
$interrompidoEm,
|
||||
$confirmacoes->count()
|
||||
);
|
||||
|
||||
$cronograma = self::calcularCronograma($item, $inicio, $confirmacoes);
|
||||
$adesao = self::calcularAdesao($item, $inicioEm, $confirmacoes->count());
|
||||
|
||||
self::log($pacienteId, 'CONSULTA_MONITORAMENTO', $item->receita_id, $receitaItemId);
|
||||
|
||||
return [
|
||||
'receita_item_id' => $receitaItemId,
|
||||
'medicamento' => $item->material->descricao,
|
||||
'posologia_incompleta' => is_null($item->intervalo_tempo) || is_null($item->durante_tempo),
|
||||
'status' => $status,
|
||||
'inicio_em' => $inicioEm,
|
||||
'interrompido_em' => $interrompidoEm,
|
||||
'adesao' => $adesao,
|
||||
'cronograma' => $cronograma,
|
||||
];
|
||||
}
|
||||
|
||||
public static function store(int $receitaItemId): array
|
||||
{
|
||||
self::verificarParametrizacao();
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$item = ReceitaItem::findOrFail($receitaItemId);
|
||||
abort_if($item->receita->paciente_id !== $pacienteId, Response::HTTP_FORBIDDEN);
|
||||
|
||||
$inicio = ReceitaTratamentoInicio::where('receita_item_id', $receitaItemId)
|
||||
->where('paciente_id', $pacienteId)
|
||||
->first();
|
||||
|
||||
abort_if(is_null($inicio), Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
abort_if(!is_null($inicio->interrompido_em), Response::HTTP_FORBIDDEN);
|
||||
|
||||
request()->validate([
|
||||
'confirmado_em' => ['required', 'date'],
|
||||
'dose_numero' => ['required', 'integer', 'min:1'],
|
||||
'observacao' => ['nullable', 'string', 'max:500'],
|
||||
]);
|
||||
|
||||
$monitoramento = ReceitaMonitoramentoPosologia::create([
|
||||
'receita_item_id' => $receitaItemId,
|
||||
'paciente_id' => $pacienteId,
|
||||
'confirmado_em' => request()->input('confirmado_em'),
|
||||
'dose_numero' => request()->input('dose_numero'),
|
||||
'observacao' => request()->input('observacao'),
|
||||
]);
|
||||
|
||||
self::log($pacienteId, 'CONFIRMAR_DOSE', $item->receita_id, $receitaItemId);
|
||||
|
||||
return ['id' => $monitoramento->id];
|
||||
}
|
||||
|
||||
public static function destroy(int $id): array
|
||||
{
|
||||
self::verificarParametrizacao();
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$monitoramento = ReceitaMonitoramentoPosologia::findOrFail($id);
|
||||
abort_if($monitoramento->paciente_id !== $pacienteId, Response::HTTP_FORBIDDEN);
|
||||
|
||||
$receitaId = $monitoramento->receitaItem->receita_id;
|
||||
$receitaItemId = $monitoramento->receita_item_id;
|
||||
|
||||
$monitoramento->delete();
|
||||
|
||||
self::log($pacienteId, 'CANCELAR_DOSE', $receitaId, $receitaItemId);
|
||||
|
||||
return ['removido' => true];
|
||||
}
|
||||
|
||||
public static function interromper(int $receitaItemId): array
|
||||
{
|
||||
self::verificarParametrizacao();
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$item = ReceitaItem::findOrFail($receitaItemId);
|
||||
abort_if($item->receita->paciente_id !== $pacienteId, Response::HTTP_FORBIDDEN);
|
||||
|
||||
$inicio = ReceitaTratamentoInicio::where('receita_item_id', $receitaItemId)
|
||||
->where('paciente_id', $pacienteId)
|
||||
->whereNull('interrompido_em')
|
||||
->firstOrFail();
|
||||
|
||||
$inicio->update(['interrompido_em' => Carbon::now()]);
|
||||
|
||||
self::log($pacienteId, 'INTERROMPER_MONITORAMENTO', $item->receita_id, $receitaItemId);
|
||||
|
||||
return ['interrompido' => true];
|
||||
}
|
||||
|
||||
private static function calcularStatus(
|
||||
?int $duranteTempo,
|
||||
?int $intervaloTempo,
|
||||
?int $intervaloMedidaTempoId,
|
||||
?Carbon $inicioEm,
|
||||
?Carbon $interrompidoEm,
|
||||
int $totalConfirmadas
|
||||
): string {
|
||||
|
||||
if (is_null($inicioEm)) {
|
||||
|
||||
return MonitoramentoPosologia::STATUS_NAO_INICIADO;
|
||||
}
|
||||
|
||||
if (!is_null($interrompidoEm)) {
|
||||
|
||||
return MonitoramentoPosologia::STATUS_INTERROMPIDO;
|
||||
}
|
||||
|
||||
if (is_null($duranteTempo) || is_null($intervaloTempo)) {
|
||||
|
||||
return MonitoramentoPosologia::STATUS_EM_ANDAMENTO;
|
||||
}
|
||||
|
||||
$intervaloMinutos = self::calcularIntervaloEmMinutos($intervaloTempo, $intervaloMedidaTempoId);
|
||||
|
||||
if ($intervaloMinutos > 0) {
|
||||
|
||||
$totalDosesPrevistas = (int) ceil(($duranteTempo * 24 * 60) / $intervaloMinutos);
|
||||
|
||||
if ($totalConfirmadas >= $totalDosesPrevistas) {
|
||||
|
||||
return MonitoramentoPosologia::STATUS_FINALIZADO;
|
||||
}
|
||||
}
|
||||
|
||||
$fimTratamento = $inicioEm->copy()->addDays($duranteTempo);
|
||||
|
||||
if (Carbon::now()->lessThanOrEqualTo($fimTratamento)) {
|
||||
|
||||
return MonitoramentoPosologia::STATUS_EM_ANDAMENTO;
|
||||
}
|
||||
|
||||
return $totalConfirmadas > 0 ? MonitoramentoPosologia::STATUS_FINALIZADO : MonitoramentoPosologia::STATUS_EXPIRADO;
|
||||
}
|
||||
|
||||
private static function calcularCronograma(ReceitaItem $item, ?ReceitaTratamentoInicio $inicio, Collection $confirmacoes): array
|
||||
{
|
||||
if (is_null($inicio) || is_null($item->intervalo_tempo) || is_null($item->durante_tempo)) {
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$intervaloMinutos = self::calcularIntervaloEmMinutos($item->intervalo_tempo, $item->intervalo_medida_tempo_id);
|
||||
|
||||
if ($intervaloMinutos <= 0) {
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$duracaoMinutos = $item->durante_tempo * 24 * 60;
|
||||
$totalDoses = (int) ceil($duracaoMinutos / $intervaloMinutos);
|
||||
|
||||
$confirmacoesPorNumero = $confirmacoes->keyBy('dose_numero');
|
||||
|
||||
$cronograma = [];
|
||||
|
||||
for ($i = 0; $i < $totalDoses; $i++) {
|
||||
|
||||
$doseNumero = $i + 1;
|
||||
$esperadoEm = $inicio->inicio_em->copy()->addMinutes($i * $intervaloMinutos);
|
||||
$confirmacao = $confirmacoesPorNumero->get($doseNumero);
|
||||
|
||||
if ($confirmacao) {
|
||||
|
||||
$statusDose = MonitoramentoPosologia::STATUS_DOSE_CONFIRMADA;
|
||||
} elseif ($esperadoEm->copy()->addMinutes(MonitoramentoPosologia::TOLERANCIA_ATRASO_MINUTOS)->isPast()) {
|
||||
|
||||
$statusDose = MonitoramentoPosologia::STATUS_DOSE_ATRASADA;
|
||||
} else {
|
||||
|
||||
$statusDose = MonitoramentoPosologia::STATUS_DOSE_PENDENTE;
|
||||
}
|
||||
|
||||
$cronograma[] = [
|
||||
'id' => $confirmacao ? $confirmacao->id : null,
|
||||
'numero' => $doseNumero,
|
||||
'esperado_em' => $esperadoEm->toDateTimeString(),
|
||||
'confirmado_em' => $confirmacao ? $confirmacao->confirmado_em : null,
|
||||
'status' => $statusDose,
|
||||
'observacao' => $confirmacao ? $confirmacao->observacao : null,
|
||||
];
|
||||
}
|
||||
|
||||
return $cronograma;
|
||||
}
|
||||
|
||||
private static function calcularIntervaloEmMinutos(int $intervalo, ?int $medidaTempoId): int
|
||||
{
|
||||
if ($medidaTempoId === MedidaTempo::MINUTOS) {
|
||||
|
||||
return $intervalo;
|
||||
}
|
||||
|
||||
if ($medidaTempoId === MedidaTempo::DIAS) {
|
||||
|
||||
return $intervalo * 24 * 60;
|
||||
}
|
||||
|
||||
if ($medidaTempoId === MedidaTempo::SEMANAS) {
|
||||
|
||||
return $intervalo * 7 * 24 * 60;
|
||||
}
|
||||
|
||||
return $intervalo * 60;
|
||||
}
|
||||
|
||||
private static function calcularAdesao(ReceitaItem $item, ?Carbon $inicioEm, int $confirmadas): array
|
||||
{
|
||||
if (is_null($inicioEm) || is_null($item->intervalo_tempo) || is_null($item->durante_tempo)) {
|
||||
|
||||
return [
|
||||
'doses_previstas' => null,
|
||||
'doses_confirmadas' => $confirmadas,
|
||||
'percentual' => null,
|
||||
];
|
||||
}
|
||||
|
||||
$intervaloMinutos = self::calcularIntervaloEmMinutos($item->intervalo_tempo, $item->intervalo_medida_tempo_id);
|
||||
$duracaoMinutos = $item->durante_tempo * 24 * 60;
|
||||
$decorridoMinutos = min($inicioEm->diffInMinutes(Carbon::now()), $duracaoMinutos);
|
||||
|
||||
$previstas = $intervaloMinutos > 0 ? (int) ceil($decorridoMinutos / $intervaloMinutos) : 0;
|
||||
$percentual = $previstas > 0 ? round(($confirmadas / $previstas) * 100, 1) : null;
|
||||
|
||||
return [
|
||||
'doses_previstas' => $previstas,
|
||||
'doses_confirmadas' => $confirmadas,
|
||||
'percentual' => $percentual,
|
||||
];
|
||||
}
|
||||
|
||||
private static function montarPosologiaTexto(object $row): ?string
|
||||
{
|
||||
$texto = '';
|
||||
|
||||
if (!is_null($row->quantidade)) {
|
||||
|
||||
$quantidade = (float) $row->quantidade;
|
||||
$texto .= fmod($quantidade, 1) == 0 ? (int) $quantidade : number_format($quantidade, 2, ',', '.');
|
||||
|
||||
if ($row->unidade_medida_nome) {
|
||||
|
||||
$texto .= ' ' . strtolower($row->unidade_medida_nome);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($row->intervalo_tempo)) {
|
||||
|
||||
$intervalo = (int) $row->intervalo_tempo;
|
||||
|
||||
if ($row->intervalo_medida_tempo_nome) {
|
||||
|
||||
$unidade = strtolower(self::pluralizar($row->intervalo_medida_tempo_nome, $intervalo));
|
||||
$texto .= $intervalo === 1
|
||||
? " a cada {$unidade}"
|
||||
: " a cada {$intervalo} {$unidade}";
|
||||
} else {
|
||||
|
||||
$texto .= " a cada {$intervalo}";
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($row->durante_tempo)) {
|
||||
|
||||
$dias = (int) $row->durante_tempo;
|
||||
$texto .= $dias === 1 ? ' durante 1 dia' : " durante {$dias} dias";
|
||||
}
|
||||
|
||||
return empty($texto) ? null : $texto;
|
||||
}
|
||||
|
||||
private static function pluralizar(string $nome, int $valor): string
|
||||
{
|
||||
if (strpos($nome, '(es)') !== false) {
|
||||
|
||||
return $valor === 1
|
||||
? str_replace('(es)', '', $nome)
|
||||
: str_replace('(es)', 'es', $nome);
|
||||
}
|
||||
|
||||
if (strpos($nome, '(s)') !== false) {
|
||||
|
||||
return $valor === 1
|
||||
? str_replace('(s)', '', $nome)
|
||||
: str_replace('(s)', 's', $nome);
|
||||
}
|
||||
|
||||
return $nome;
|
||||
}
|
||||
|
||||
private static function verificarParametrizacao(): void
|
||||
{
|
||||
$parametrizacao = ParametrizacaoAppCidadao::first();
|
||||
abort_if(!($parametrizacao->permite_envio_receitas_medicas ?? false), Response::HTTP_FORBIDDEN);
|
||||
}
|
||||
|
||||
private static function log(int $pacienteId, string $tipoAcao, ?int $receitaId = null, ?int $receitaItemId = null): void
|
||||
{
|
||||
AppCidadaoLog::create([
|
||||
'paciente_id' => $pacienteId,
|
||||
'receita_id' => $receitaId,
|
||||
'receita_item_id' => $receitaItemId,
|
||||
'tipo_acao' => $tipoAcao,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Mobile\ConectaCidadao\Farmacia;
|
||||
|
||||
use App\Enums\Geral\MedidaTempo;
|
||||
use App\Models\Farmacia\AppCidadaoLog;
|
||||
use App\Models\Farmacia\ParametrizacaoAppCidadao;
|
||||
use App\Services\Service;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ReceitaService extends Service
|
||||
{
|
||||
public static function index(): array
|
||||
{
|
||||
$parametrizacao = ParametrizacaoAppCidadao::first();
|
||||
|
||||
if (!($parametrizacao->permite_envio_receitas_medicas ?? false)) {
|
||||
|
||||
return ['habilitado' => false];
|
||||
}
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
$perPage = (int) request()->input('per_page', 15);
|
||||
$page = (int) request()->input('page', 1);
|
||||
|
||||
$todos = self::queryAmbulatorioIds($pacienteId)->get()->map(
|
||||
function ($r) {
|
||||
return (array) $r;
|
||||
}
|
||||
);
|
||||
|
||||
$total = $todos->count();
|
||||
$lastPage = max(1, (int) ceil($total / $perPage));
|
||||
$page = max(1, min($page, $lastPage));
|
||||
$slice = $todos->sortByDesc('data')->slice(($page - 1) * $perPage, $perPage)->values();
|
||||
$ids = $slice->pluck('id')->toArray();
|
||||
|
||||
$receitas = collect();
|
||||
|
||||
if (!empty($ids)) {
|
||||
|
||||
$rows = self::queryAmbulatorioDetalhes($ids)->get();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$receitas->push(
|
||||
[
|
||||
'id' => $row->prescricao_id,
|
||||
'data_emissao' => $row->data_receita,
|
||||
'validade' => null,
|
||||
'situacao' => 'ativa',
|
||||
'unidade' => $row->unidade_nome,
|
||||
'prescritor' => $row->prescritor_nome,
|
||||
'total_itens' => $row->total_itens,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self::log($pacienteId, 'LISTA_RECEITAS');
|
||||
|
||||
return [
|
||||
'habilitado' => true,
|
||||
'data' => $receitas->sortByDesc('data_emissao')->values(),
|
||||
'current_page' => $page,
|
||||
'last_page' => $lastPage,
|
||||
'total' => $total,
|
||||
'per_page' => $perPage,
|
||||
];
|
||||
}
|
||||
|
||||
public static function show(int $id): array
|
||||
{
|
||||
$parametrizacao = ParametrizacaoAppCidadao::first();
|
||||
|
||||
if (!($parametrizacao->permite_envio_receitas_medicas ?? false)) {
|
||||
|
||||
return ['habilitado' => false];
|
||||
}
|
||||
|
||||
$pacienteId = auth('mobile')->user()->id;
|
||||
|
||||
$pacienteNome = DB::table('cadastro_paciente')
|
||||
->join('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_paciente.cidadao_id')
|
||||
->where('cadastro_paciente.id', $pacienteId)
|
||||
->value('cadastro_cidadao.nome');
|
||||
|
||||
$header = DB::table('ambulatorio_atendimento_soap_prescricao_medicamento as prescricao')
|
||||
->select(
|
||||
'prescricao.id',
|
||||
'prescricao.created_at as data_receita',
|
||||
'prescritor_cidadao.nome as prescritor_nome',
|
||||
'cadastro_unidade.nome_fantasia as unidade_nome',
|
||||
'cid.codigo as cid_codigo',
|
||||
'cid.nome as cid_nome'
|
||||
)
|
||||
->join('ambulatorio_atendimento_soap as soap', 'soap.id', 'prescricao.soap_id')
|
||||
->join('ambulatorio_atendimento as atendimento', 'atendimento.id', 'soap.atendimento_id')
|
||||
->leftJoin('cadastro_lotacao', 'cadastro_lotacao.id', 'prescricao.created_lotacao_id')
|
||||
->leftJoin('cadastro_usuario', 'cadastro_usuario.id', 'cadastro_lotacao.usuario_id')
|
||||
->leftJoin('cadastro_cidadao as prescritor_cidadao', 'prescritor_cidadao.id', 'cadastro_usuario.cidadao_id')
|
||||
->leftJoin('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_lotacao.infraestrutura_id')
|
||||
->leftJoin('cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id')
|
||||
->leftJoin(
|
||||
DB::raw('(SELECT soap_id, MIN(cid_id) as cid_id FROM ambulatorio_atendimento_soap_problema_condicao WHERE cid_id IS NOT NULL GROUP BY soap_id) as cond'),
|
||||
'cond.soap_id',
|
||||
'=',
|
||||
'soap.id'
|
||||
)
|
||||
->leftJoin('sigtap.cid as cid', 'cid.id', 'cond.cid_id')
|
||||
->where('prescricao.id', $id)
|
||||
->where(function ($q) use ($pacienteId) {
|
||||
$q->whereExists(function ($q2) use ($pacienteId) {
|
||||
$q2->select(DB::raw(1))
|
||||
->from('ambulatorio_agendamento as ag')
|
||||
->whereColumn('ag.id', 'atendimento.agendamento_id')
|
||||
->where('ag.paciente_id', $pacienteId);
|
||||
})->orWhereExists(function ($q2) use ($pacienteId) {
|
||||
$q2->select(DB::raw(1))
|
||||
->from('ambulatorio_demanda_espontanea as de')
|
||||
->whereColumn('de.id', 'atendimento.demanda_espontanea_id')
|
||||
->where('de.paciente_id', $pacienteId);
|
||||
});
|
||||
})
|
||||
->first();
|
||||
|
||||
abort_if(!$header, Response::HTTP_NOT_FOUND);
|
||||
|
||||
$itens = DB::table('ambulatorio_atendimento_soap_prescricao_medicamento_item as item')
|
||||
->select(
|
||||
'item.id',
|
||||
'item.material_id',
|
||||
'item.descricao as item_descricao',
|
||||
'item.justificativa',
|
||||
'item.dose',
|
||||
'item.intervalo',
|
||||
'item.duracao',
|
||||
'item.duracao_medida_tempo_id',
|
||||
'item.recomendacoes',
|
||||
'medida_tempo.nome as intervalo_medida_tempo_nome',
|
||||
'unidade_medida.nome as apresentacao_unidade_medida',
|
||||
'cadastro_via_administracao.nome as via_administracao',
|
||||
DB::raw("CASE WHEN item.material_id IS NOT NULL THEN cadastro_material.descricao ELSE item.descricao END AS material_descricao")
|
||||
)
|
||||
->leftJoin('cadastro_material', 'cadastro_material.id', 'item.material_id')
|
||||
->leftJoin('cadastro_unidade_medida AS unidade_medida', 'unidade_medida.id', 'item.unidade_medida_id')
|
||||
->leftJoin('geral_medida_tempo as medida_tempo', 'medida_tempo.id', 'item.intervalo_medida_tempo_id')
|
||||
->leftJoin('cadastro_via_administracao', 'cadastro_via_administracao.id', 'cadastro_material.via_administracao_id')
|
||||
->where('item.prescricao_medicamento_id', $id)
|
||||
->get()
|
||||
->map(
|
||||
function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'tipo' => is_null($item->material_id) ? 'nao_padronizado' : 'padronizado',
|
||||
'medicamento' => $item->material_descricao,
|
||||
'justificativa' => is_null($item->material_id) ? $item->justificativa : null,
|
||||
'posologia_texto' => self::montarPosologiaTexto($item),
|
||||
'posologia_incompleta' => is_null($item->intervalo),
|
||||
'unidade_medida' => $item->apresentacao_unidade_medida,
|
||||
'intervalo_tempo' => $item->intervalo,
|
||||
'intervalo_medida_tempo' => $item->intervalo_medida_tempo_nome,
|
||||
'durante_tempo' => self::calcularDuracaoEmDias($item->duracao, $item->duracao_medida_tempo_id),
|
||||
'via_administracao' => $item->via_administracao,
|
||||
'recomendacoes' => $item->recomendacoes,
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
self::log($pacienteId, 'DETALHE_RECEITA', $id);
|
||||
|
||||
return [
|
||||
'id' => $header->id,
|
||||
'paciente' => $pacienteNome,
|
||||
'data_emissao' => $header->data_receita,
|
||||
'validade' => null,
|
||||
'situacao' => 'ativa',
|
||||
'cid' => [
|
||||
'codigo' => $header->cid_codigo,
|
||||
'descricao' => $header->cid_nome,
|
||||
],
|
||||
'prescritor' => $header->prescritor_nome,
|
||||
'unidade' => $header->unidade_nome,
|
||||
'itens' => $itens,
|
||||
];
|
||||
}
|
||||
|
||||
private static function queryAmbulatorioIds(int $pacienteId)
|
||||
{
|
||||
return DB::table('ambulatorio_atendimento_soap_prescricao_medicamento as prescricao')
|
||||
->select('prescricao.id', 'prescricao.created_at as data')
|
||||
->join('ambulatorio_atendimento_soap as soap', 'soap.id', 'prescricao.soap_id')
|
||||
->join('ambulatorio_atendimento as atendimento', 'atendimento.id', 'soap.atendimento_id')
|
||||
->where('prescricao.solicitacao_fechada', false)
|
||||
->where(function ($q) use ($pacienteId) {
|
||||
$q->whereExists(function ($q2) use ($pacienteId) {
|
||||
$q2->select(DB::raw(1))
|
||||
->from('ambulatorio_agendamento as ag')
|
||||
->whereColumn('ag.id', 'atendimento.agendamento_id')
|
||||
->where('ag.paciente_id', $pacienteId);
|
||||
})->orWhereExists(function ($q2) use ($pacienteId) {
|
||||
$q2->select(DB::raw(1))
|
||||
->from('ambulatorio_demanda_espontanea as de')
|
||||
->whereColumn('de.id', 'atendimento.demanda_espontanea_id')
|
||||
->where('de.paciente_id', $pacienteId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static function queryAmbulatorioDetalhes(array $ids)
|
||||
{
|
||||
return DB::table('ambulatorio_atendimento_soap_prescricao_medicamento as prescricao')
|
||||
->select(
|
||||
'prescricao.id as prescricao_id',
|
||||
'prescricao.created_at as data_receita',
|
||||
'prescritor_cidadao.nome as prescritor_nome',
|
||||
'cadastro_unidade.nome_fantasia as unidade_nome',
|
||||
DB::raw('(SELECT COUNT(*) FROM ambulatorio_atendimento_soap_prescricao_medicamento_item WHERE prescricao_medicamento_id = prescricao.id) as total_itens')
|
||||
)
|
||||
->leftJoin('cadastro_lotacao', 'cadastro_lotacao.id', 'prescricao.created_lotacao_id')
|
||||
->leftJoin('cadastro_usuario', 'cadastro_usuario.id', 'cadastro_lotacao.usuario_id')
|
||||
->leftJoin('cadastro_cidadao as prescritor_cidadao', 'prescritor_cidadao.id', 'cadastro_usuario.cidadao_id')
|
||||
->leftJoin('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_lotacao.infraestrutura_id')
|
||||
->leftJoin('cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id')
|
||||
->whereIn('prescricao.id', $ids);
|
||||
}
|
||||
|
||||
private static function calcularDuracaoEmDias(?int $duracao, ?int $medidaTempoId): ?int
|
||||
{
|
||||
if (is_null($duracao)) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($medidaTempoId === MedidaTempo::HORAS) {
|
||||
|
||||
return max(1, (int) ceil($duracao / 24));
|
||||
}
|
||||
|
||||
if ($medidaTempoId === MedidaTempo::SEMANAS) {
|
||||
|
||||
return $duracao * 7;
|
||||
}
|
||||
|
||||
if ($medidaTempoId === MedidaTempo::MESES) {
|
||||
|
||||
return $duracao * 30;
|
||||
}
|
||||
|
||||
return $duracao;
|
||||
}
|
||||
|
||||
private static function pluralizar(string $nome, int $valor): string
|
||||
{
|
||||
if (strpos($nome, '(es)') !== false) {
|
||||
|
||||
return $valor === 1
|
||||
? str_replace('(es)', '', $nome)
|
||||
: str_replace('(es)', 'es', $nome);
|
||||
}
|
||||
|
||||
if (strpos($nome, '(s)') !== false) {
|
||||
|
||||
return $valor === 1
|
||||
? str_replace('(s)', '', $nome)
|
||||
: str_replace('(s)', 's', $nome);
|
||||
}
|
||||
|
||||
return $nome;
|
||||
}
|
||||
|
||||
private static function montarPosologiaTexto($row): ?string
|
||||
{
|
||||
$texto = '';
|
||||
|
||||
if (!is_null($row->dose)) {
|
||||
|
||||
$dose = (float) trim($row->dose);
|
||||
$texto .= fmod($dose, 1) == 0 ? (int) $dose : number_format($dose, 2, ',', '.');
|
||||
|
||||
if ($row->apresentacao_unidade_medida) {
|
||||
|
||||
$texto .= ' ' . strtolower($row->apresentacao_unidade_medida);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($row->intervalo)) {
|
||||
|
||||
$intervalo = (int) $row->intervalo;
|
||||
|
||||
if ($row->intervalo_medida_tempo_nome) {
|
||||
|
||||
$unidade = strtolower(self::pluralizar($row->intervalo_medida_tempo_nome, $intervalo));
|
||||
$texto .= $intervalo === 1
|
||||
? " a cada {$unidade}"
|
||||
: " a cada {$intervalo} {$unidade}";
|
||||
} else {
|
||||
|
||||
$texto .= " a cada {$intervalo}";
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($row->duracao)) {
|
||||
|
||||
$dias = self::calcularDuracaoEmDias((int) $row->duracao, $row->duracao_medida_tempo_id);
|
||||
|
||||
if (!is_null($dias)) {
|
||||
|
||||
$texto .= $dias === 1 ? ' durante 1 dia' : " durante {$dias} dias";
|
||||
}
|
||||
}
|
||||
|
||||
return empty($texto) ? null : $texto;
|
||||
}
|
||||
|
||||
private static function log(int $pacienteId, string $tipoAcao, ?int $receitaId = null): void
|
||||
{
|
||||
AppCidadaoLog::create(
|
||||
[
|
||||
'paciente_id' => $pacienteId,
|
||||
'receita_id' => $receitaId,
|
||||
'tipo_acao' => $tipoAcao,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user