Files
rkm-conectasus-ci-sandbox/api/app/Services/Farmacia/ReceitaService.php
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

1917 lines
76 KiB
PHP

<?php
namespace App\Services\Farmacia;
use App\Enums\Cadastro\Grupo\GrupoTipo;
use App\Enums\Geral\MedidaTempo;
use App\Models\Almoxarifado\SaidaItem;
use App\Models\Ambulatorio\AtendimentoSoapPrescricaoMedicamento;
use App\Models\Cadastro\Estabelecimento\CentroCusto;
use App\Models\Cadastro\Material\Material;
use App\Models\Cadastro\SujeitoAtencao\Paciente;
use App\Models\Farmacia\MedicamentoNaoPadronizado;
use App\Models\Farmacia\ParametrizacaoDispensacao;
use App\Models\Farmacia\ParametrizacaoLimitePrescricaoMedicamento;
use App\Models\Farmacia\ParametrizacaoMedicamentoSupervisor;
use App\Models\Farmacia\ParametrizacaoPosologia;
use App\Models\Farmacia\Receita;
use App\Models\Farmacia\ReceitaItem;
use App\Models\Farmacia\ReceitaItemEntrega;
use App\Models\Farmacia\Supervisor;
use App\Models\Intranet\Cliente;
use App\Models\PainelSenha\Fila;
use App\Services\Almoxarifado\AlmoxarifadoService;
use App\Services\Cadastro\Material\MaterialService;
use App\Services\Integracao\CnsService;
use App\Services\Service;
use App\Utils\DataUtil;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class ReceitaService extends Service
{
public static function create($pacienteId, $filaId)
{
if (isset($filaId)) {
$fila = Fila::findOrFail($filaId);
FilaAtendimentoService::answer($fila->id);
}
$receita = new Receita;
$receita->fill(array_fill_keys($receita->getFillable(), null));
$receita->isReceitaSus = true;
$receita->isRemedioEmCasa = false;
$item = new ReceitaItem;
$item->fill(array_fill_keys($item->getFillable(), null));
$item->id = null;
$item->entregue = null;
$item->continuo = false;
$item->estoque = 0;
$item->escolheu_entrada_item_manualmente = false;
$item->entrada_itens = [];
$item->possui_entrada_com_lote = false;
$item->supervisor_id = null;
$item->dispensado_em = null;
$item->programa = null;
$medicamentosNaoPadronizados = new MedicamentoNaoPadronizado;
$medicamentosNaoPadronizados->fill(array_fill_keys($medicamentosNaoPadronizados->getFillable(), null));
$medicamentosNaoPadronizados->id = null;
$parametrizacaoLimitePrescricaoMedicamento = ParametrizacaoLimitePrescricaoMedicamento::first();
$limitePrescricaoMedicamento = isset($parametrizacaoLimitePrescricaoMedicamento) ? $parametrizacaoLimitePrescricaoMedicamento->limite_dias : 180;
$paciente = self::getPaciente($pacienteId);
$lastUpdated = self::getLastUpdated($paciente);
$medicamentoSupervisor = ParametrizacaoMedicamentoSupervisor::first();
$parametrizacaoPosologia = ParametrizacaoPosologia::first();
$currentLotacao = self::getCurrentLotacao();
$cliente = Cliente::where('link', app('config')->get('database.default'))->firstOrFail();
$parametrizacaoDispensacao = ParametrizacaoDispensacao::first();
return [
'additionals' => [
'permissoes_atualizacao_cadastro_paciente' => self::getPermissoesAtualizacaoCadastroPaciente(),
],
'form' => [
'data_atual' => Carbon::now()->format('d/m/Y'),
'paciente' => $paciente,
'ultima_atualizacao_cadastral' => $lastUpdated,
'unidades_medida_tempo' => self::getUnidadesMedidaTempo(),
'receitas_pendentes' => self::getReceitasPendentes($paciente),
'receitas_historico' => self::getHistoricoReceitas($pacienteId),
'medicamentos_nao_padronizados_cadastrados' => self::getMedicamentosNaoPadronizadosCadastrados(),
'medicamento_supervisor_dispensar' => $medicamentoSupervisor->dispensar ?? null,
'posologia_is_obrigatorio' => $parametrizacaoPosologia->is_obrigatorio ?? null,
'cliente' => [
'sistema' => [
'ramo_atividade' => [
'nome' => $cliente->sistema->ramoAtividade->nome ?? null,
],
'nome' => $cliente->sistema->nome ?? null,
'versao' => $cliente->sistema->versao ?? null,
],
'municipio' => [
'estado' => [
'uf' => $cliente->municipio->estado->uf ?? null,
],
'nome' => $cliente->municipio->nome ?? null,
],
'nome' => $cliente->nome ?? null,
'email' => $cliente->email ?? null,
'site' => $cliente->site ?? null,
'logotipo' => $cliente->logotipo ?? null,
],
'usuario' => $currentLotacao->usuario->cidadao->nome,
'unidade' => $currentLotacao->infraestrutura->unidade->nome_fantasia,
'telefone' => MaskUtil::getPhoneMasked($currentLotacao->infraestrutura->telefone),
'solicitacoes_medicamentos' => ($parametrizacaoDispensacao->utiliza_solicitacao_medicamentos_ambulatorio ?? false)
? self::getSolicitacoesMedicamentos($pacienteId)
: [],
],
'model' => array_merge(
$receita->makeHidden(['id'])->toArray(),
[
'medico_solicitante' => null,
'cid' => null,
'item' => $item->toArray(),
'items' => [],
'receitas_pendentes_deleted' => [],
'items_entregas_estornados' => [],
'medicamento_nao_padronizado' => $medicamentosNaoPadronizados->toArray(),
'medicamentos_nao_padronizados' => self::getMedicamentosNaoPadronizados($pacienteId),
'limite_dias_prescricao_medicamento'=> $limitePrescricaoMedicamento,
'paciente' => [
'id' => $paciente->id,
'observacao' => $paciente->observacao,
'save' => null,
],
],
),
];
}
private static function getPaciente($id)
{
return Paciente::with(
'unidade',
'cidadao.domicilio.endereco.logradouro.municipio.estado',
'responsavel.usuario.cidadao',
'responsavel.equipe.area',
'responsavel.equipe.microarea',
)->findOrFail($id);
}
private static function getUnidadesMedidaTempo()
{
return DB::table('geral_medida_tempo')
->select(
'id',
'nome'
)
->get();
}
private static function getReceitasPendentes($paciente)
{
$receitas = DB::table('farmacia_receita')
->select(
'farmacia_receita.id',
'farmacia_receita.ambulatorio_prescricao_medicamento_id',
'farmacia_receita.usuario_id',
DB::raw('DATE_FORMAT(farmacia_receita.data_receita, "%d/%m/%Y") AS data_receita'),
'farmacia_receita.numero_notificacao',
'farmacia_receita.cid_id',
'farmacia_receita.is_receita_sus',
'farmacia_receita.is_remedio_em_casa',
'farmacia_receita.observacao',
'farmacia_receita_item.id AS item_id',
'farmacia_receita_item.durante_tempo',
'farmacia_receita_item.intervalo_medida_tempo_id',
'farmacia_receita_item.intervalo_tempo',
'farmacia_receita_item.material_id',
'farmacia_receita_item.observacao AS item_observacao',
'farmacia_receita_item.prescrito',
'farmacia_receita_item.proxima_retirada',
'farmacia_receita_item.quantidade',
'farmacia_receita_item.receita_id',
'usuario_cidadao.nome AS usuario_nome',
'cid.codigo AS cid_codigo',
'cid.nome AS cid_nome',
DB::raw(MaterialService::getDescricaoCompletaRaw(
'cadastro_material',
'cadastro_apresentacao',
'apresentacao_unidade_medida'
) . " AS material_descricao"),
DB::raw("TRIM(cadastro_material.quantidade)+0 AS material_quantidade"),
'cadastro_apresentacao.nome AS material_apresentacao',
DB::raw("
(
SELECT frie.quantidade
FROM farmacia_receita_item_entrega frie
WHERE frie.receita_item_id = farmacia_receita_item.id
AND frie.pendente = 1
) AS saldo
"),
DB::raw("
(
SELECT DATE_FORMAT(frie.dispensado_em, '%d/%m/%Y')
FROM farmacia_receita_item_entrega frie
WHERE frie.receita_item_id = farmacia_receita_item.id
AND frie.pendente = 0
AND frie.estornado = 0
ORDER BY frie.id DESC
LIMIT 1
) AS ultima_saida
")
)
->join(
'cadastro_usuario',
'cadastro_usuario.id',
'farmacia_receita.usuario_id'
)
->join(
'cadastro_cidadao AS usuario_cidadao',
'usuario_cidadao.id',
'cadastro_usuario.cidadao_id'
)
->leftJoin(
'sigtap.cid AS cid',
'sigtap.cid.id',
'farmacia_receita.cid_id',
)
->join(
'farmacia_receita_item',
'farmacia_receita_item.receita_id',
'farmacia_receita.id'
)
->join(
'geral_medida_tempo',
'geral_medida_tempo.id',
'farmacia_receita_item.intervalo_medida_tempo_id',
)
->join(
'cadastro_material',
'cadastro_material.id',
'farmacia_receita_item.material_id'
)
->join(
'cadastro_apresentacao',
'cadastro_apresentacao.id',
'cadastro_material.apresentacao_id'
)
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'farmacia_receita.created_centro_custo_id'
)
->leftJoin(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'cadastro_material.apresentacao_unidade_medida_id'
)
->where('centro_custo.id', self::getCentroCustoLogado()->id)
->where('farmacia_receita.paciente_id', $paciente->id)
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('farmacia_receita_item_entrega')
->whereColumn(
'farmacia_receita_item_entrega.receita_item_id',
'farmacia_receita_item.id'
)
->where('farmacia_receita_item_entrega.pendente', true);
})
->get();
$collectionReceitas = collect([]);
$receitas->map(function ($receita) use (&$collectionReceitas, $receitas) {
if (!$collectionReceitas->contains('id', $receita->id)) {
$collectionReceitas->push(
[
'id' => $receita->id,
'ambulatorio_prescricao_medicamento_id' => $receita->ambulatorio_prescricao_medicamento_id,
'usuario_id' => $receita->usuario_id,
'medico_solicitante' => [
'id' => $receita->usuario_id,
'cidadao_nome' => $receita->usuario_nome,
],
'data_receita' => $receita->data_receita,
'numero_notificacao' => $receita->numero_notificacao,
'cid_id' => $receita->cid_id,
'cid' => [
'id' => $receita->cid_id,
'nome' => $receita->cid_nome,
'codigo' => $receita->cid_codigo,
],
'is_receita_sus' => $receita->is_receita_sus == 1 ? true : false,
'is_remedio_em_casa' => $receita->is_remedio_em_casa == 1 ? true : false,
'observacao' => $receita->observacao,
'items' => self::getReceitaPendenteItems($receitas, $receita->id),
]
);
}
});
return $collectionReceitas;
}
public static function getMedicamentosAVencer() {
$quantidadeMedicamentosAvencer = DB::query()->fromSub(DB::table('cadastro_material')
->select(DB::raw(1))
->join('cadastro_grupo', 'cadastro_grupo.id', 'cadastro_material.grupo_id')
->join('almoxarifado_entrada_item', function ($join) {
$join->on('almoxarifado_entrada_item.material_id', 'cadastro_material.id')
->whereExists(function ($query) {
$query
->select(DB::raw('1'))
->from('almoxarifado_entrada')
->whereColumn('almoxarifado_entrada.id', 'almoxarifado_entrada_item.entrada_id')
->where('almoxarifado_entrada.finalizada', true)
->where('almoxarifado_entrada.centro_custo_id', self::getCurrentCentroCusto()->id);
});
})
->whereNull('cadastro_material.deleted_at')
->whereNotNull('almoxarifado_entrada_item.lote')
->where('cadastro_grupo.grupo_tipo_id', GrupoTipo::MEDICAMENTO)
->where('cadastro_material.is_ativo', true)
->whereRaw('DATEDIFF(almoxarifado_entrada_item.validade_lote, CURRENT_DATE) < 90')
->groupBy(
'cadastro_material.id',
'almoxarifado_entrada_item.lote',
'almoxarifado_entrada_item.validade_lote',
)
->havingRaw("(COALESCE(SUM(
COALESCE(almoxarifado_entrada_item.quantidade, 0)
-
COALESCE((
SELECT SUM(almoxarifado_saida_item_entrada_item.quantidade_saida)
FROM almoxarifado_saida_item_entrada_item
JOIN almoxarifado_saida_item
ON almoxarifado_saida_item.id = almoxarifado_saida_item_entrada_item.saida_item_id
JOIN almoxarifado_saida
ON almoxarifado_saida.id = almoxarifado_saida_item.saida_id
WHERE almoxarifado_saida_item_entrada_item.entrada_item_id = almoxarifado_entrada_item.id
AND almoxarifado_saida.finalizada = 1
), 0)
), 0)) > 0")
, 'sub')->count();
return ['medicamentos_a_vencer' => $quantidadeMedicamentosAvencer > 0 ? true : false];
}
private static function getReceitaPendenteItems($receitas, $receitaId)
{
return $receitas->where('id', $receitaId)->map(function ($receita) {
$material = Material::with('grupo')->findOrFail($receita->material_id);
$programa = collect([]);
if($material->grupo->grupo_tipo_id === GrupoTipo::MEDICAMENTO) {
if($material->is_programa_remedio_em_casa) $programa->push("Programa remédio em casa");
if($material->is_alto_custo) $programa->push("Alto custo");
if($material->is_acao_judicial) $programa->push("Ação judicial");
if($material->is_remume) $programa->push("REMUME");
}
$material->programa = $programa->isNotEmpty() ? implode(', ', $programa->toArray()) : '-';
$estoque = AlmoxarifadoService::getEstoque($receita->material_id);
$entregue = $receita->saldo > $estoque['total'] ? $estoque['total'] : $receita->saldo;
$entradaItensData = AlmoxarifadoService::getEntradaItensData(
$receita->material_id,
[
'escolheu_entrada_item_manualmente' => false,
'quantidade' => $entregue,
]
);
$entradaItensAutomaticos = [];
foreach ($entradaItensData as $entradaItemId => $entradaItemData) {
$entradaItensAutomaticos[] = [
'entrada_item_id' => $entradaItemId,
'quantidade_saida' => $entradaItemData['quantidade_saida'],
];
}
$entradaItens = collect($estoque['por_entrada'])
->map(function ($entradaItem) use ($entradaItensAutomaticos) {
$entradaItem['quantidade_saida'] = collect($entradaItensAutomaticos)
->where('entrada_item_id', $entradaItem['entrada_item_id'])
->first()['quantidade_saida'] ?? 0;
return $entradaItem;
});
return [
'id' => $receita->item_id,
'material_id' => $receita->material_id,
'material' => [
'id' => $receita->material_id,
'descricao' => $receita->material_descricao,
'descricao_completa' => $receita->material_descricao,
'apresentacao' => Str::upper($receita->material_apresentacao),
'quantidade' => $receita->material_quantidade,
],
'quantidade' => $receita->quantidade,
'intervalo_tempo' => $receita->intervalo_tempo,
'intervalo_medida_tempo_id' => $receita->intervalo_medida_tempo_id,
'durante_tempo' => $receita->durante_tempo,
'prescrito' => $receita->prescrito,
'programa' => $material->programa,
'entregue' => $entregue,
'saldo' => $receita->saldo,
'ultima_saida' => $receita->ultima_saida,
'estoque' => $estoque['total'],
'escolheu_entrada_item_manualmente' => false,
'entrada_itens' => $entradaItens,
'possui_entrada_com_lote' => !is_null($entradaItens->whereNotNull('lote')->first()),
'proxima_retirada' => $receita->proxima_retirada
? (new Carbon($receita->proxima_retirada))->format('d/m/Y')
: null,
'vencimento_receita' => $receita->proxima_retirada
? self::getVencimentoReceita($receita)->format('d/m/Y')
: null,
'observacao' => $receita->item_observacao,
];
})
->values();
}
public static function getVencimentoReceita($receitaItem)
{
$proximaRetirada = new Carbon($receitaItem->proxima_retirada);
if ($receitaItem->saldo > 0 && !is_null($receitaItem->prescrito)) {
$multiplier = self::getMultiplierUnidadeTempoDurante($receitaItem->intervalo_medida_tempo_id);
$days = ceil((($multiplier * $receitaItem->durante_tempo) / $receitaItem->prescrito) * $receitaItem->saldo);
return $proximaRetirada->addDays($days);
}
return $proximaRetirada;
}
public static function getMultiplierUnidadeTempoDurante($intervaloMedidaTempoId)
{
switch ($intervaloMedidaTempoId) {
case MedidaTempo::SEMANAS: return 7;
case MedidaTempo::MESES: return 3;
}
return 1;
}
public static function getHistoricoReceitas($pacienteId)
{
$receitas = DB::table('farmacia_receita')
->select(
'farmacia_receita.id',
'farmacia_receita.is_remedio_em_casa',
'farmacia_receita.observacao',
'cadastro_unidade.nome_fantasia',
'medico_cidadao.nome AS medico_solicitante',
'usuario_cidadao.nome AS usuario_nome',
'farmacia_receita_item.prescrito',
'farmacia_receita_item_entrega.id AS receita_item_entrega_id',
'farmacia_receita_item_entrega.quantidade AS entregue',
'farmacia_receita_item_entrega.saida_item_id',
'farmacia_receita_item.observacao AS item_observacao',
DB::raw("
IF(cadastro_infraestrutura.nome IS NULL,
cadastro_unidade.nome_fantasia,
cadastro_infraestrutura.nome
)as infraestrutura_nome,
DATE_FORMAT(farmacia_receita.data_receita, '%d/%m/%Y') AS data_receita,
DATE_FORMAT(farmacia_receita_item_entrega.dispensado_em, '%d/%m/%Y %H:%i') AS dispensado_em,
DATE_FORMAT(farmacia_receita_item.proxima_retirada, '%d/%m/%Y') AS proxima_retirada,
" . MaterialService::getDescricaoCompletaRaw(
'cadastro_material',
'cadastro_apresentacao',
'apresentacao_unidade_medida'
) . " AS material_descricao,
CAST(almoxarifado_saida.created_at AS DATE) as data_saida,
farmacia_receita_item_entrega.estornado AS estornado
"),
)
->join(
'farmacia_receita_item',
'farmacia_receita_item.receita_id',
'farmacia_receita.id'
)
->join(
'farmacia_receita_item_entrega',
'farmacia_receita_item_entrega.receita_item_id',
'farmacia_receita_item.id'
)
->join(
'almoxarifado_saida_item',
'almoxarifado_saida_item.id',
'farmacia_receita_item_entrega.saida_item_id'
)
->join(
'almoxarifado_saida',
'almoxarifado_saida.id',
'almoxarifado_saida_item.saida_id'
)
->join(
'cadastro_material',
'cadastro_material.id',
'farmacia_receita_item.material_id'
)
->join(
'cadastro_apresentacao',
'cadastro_apresentacao.id',
'cadastro_material.apresentacao_id'
)
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'farmacia_receita.created_centro_custo_id'
)
->leftJoin(
'cadastro_usuario',
'cadastro_usuario.id',
'farmacia_receita.usuario_id'
)
->leftJoin(
'cadastro_cidadao AS medico_cidadao',
'medico_cidadao.id',
'cadastro_usuario.cidadao_id'
)
->leftJoin(
'cadastro_lotacao',
'cadastro_lotacao.id',
'farmacia_receita.created_lotacao_id'
)
->leftJoin(
'cadastro_infraestrutura',
'cadastro_infraestrutura.id',
'cadastro_lotacao.infraestrutura_id'
)
->leftJoin(
'cadastro_unidade',
'cadastro_unidade.id',
'cadastro_infraestrutura.unidade_id'
)
->leftJoin(
'cadastro_usuario AS usuario_lotacao',
'usuario_lotacao.id',
'cadastro_lotacao.usuario_id'
)
->leftJoin(
'cadastro_cidadao AS usuario_cidadao',
'usuario_cidadao.id',
'usuario_lotacao.cidadao_id'
)
->leftJoin(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'cadastro_material.apresentacao_unidade_medida_id'
)
->where('farmacia_receita.paciente_id', $pacienteId)
->where('farmacia_receita_item_entrega.pendente', false)
->when(DataUtil::isStringBoolean(request()->query('programa_remedio_em_casa')), function ($query) {
$isProgramaRemedioEmCasa = DataUtil::getBooleanValueFromStringBoolean(request()->query('programa_remedio_em_casa'));
if ($isProgramaRemedioEmCasa) {
$query->where('farmacia_receita.is_remedio_em_casa', $isProgramaRemedioEmCasa);
}
});
$complete = request()->query('complete');
if (!$complete || ($complete && DataUtil::isStringBoolean($complete))) {
if (!$complete || !DataUtil::getBooleanValueFromStringBoolean($complete)) {
$date = Carbon::now()->subMonths(6)->startOfDay();
$receitas->where('farmacia_receita_item_entrega.created_at', '>=', $date);
}
}
$collectionReceitas = collect([]);
$receitas = $receitas->get();
$receitas->map(function ($receita) use (&$collectionReceitas, $receitas) {
if (!$collectionReceitas->contains('id', $receita->id)) {
$collectionReceitas->push([
'id' => $receita->id,
'data_receita' => $receita->data_receita,
'nome_fantasia' => $receita->nome_fantasia,
'infraestrutura' => $receita->infraestrutura_nome,
'medico_solicitante' => $receita->medico_solicitante,
'observacao' => $receita->observacao,
'is_remedio_em_casa' => $receita->is_remedio_em_casa,
'items' => self::getReceitaHistoricoItems($receitas, $receita->id),
]);
}
});
$paciente = Paciente::find($pacienteId);
DB::table('farmacia_historico_dispensacao_v1')
->where('cidadao_id', $paciente->cidadao->id)
->when(!$complete, fn($q) => $q->where('data_solicitacao', '>=', Carbon::now()->subMonths(6)->startOfDay()))
->get()
->each(function($query) use (&$collectionReceitas, $paciente) {
$collectionReceitas->push([
'id' => null,
'id_v1' => $query->id,
'data_receita' => Carbon::parse($query->data_solicitacao)->format('d/m/Y'),
'nome_fantasia' => $query->nome_unidade,
'infraestrutura' => $query->nome_unidade,
'medico_solicitante' => $query->nome_medico,
'observacao' => $query->observacao,
'items' => [
[
'receita_item_entrega_id' => null,
'material' => [
'descricao' => $query->nome_medicamento,
],
'lotes' => [$query->lote],
'dispensado_em' => Carbon::parse($query->data_hora_dispensacao)->format('d/m/Y H:i'),
'prescrito' => $query->quantidade_receita,
'entregue' => $query->quantidade,
'proxima_retirada' => Carbon::parse($query->data_proxima_retirada)->format('d/m/Y'),
'observacao' => $query->observacao,
'data_saida' => null,
'estornado' => null,
'estorno_salvo' => null,
]
],
]);
});
return $collectionReceitas->sortByDesc(fn($q) => Carbon::createFromFormat('d/m/Y', $q['data_receita'])->timestamp)->values()->all();
}
private static function getReceitaHistoricoItems($receitas, $receitaId)
{
return $receitas->where('id', $receitaId)->map(function ($receita) {
$lotes = collect();
SaidaItem::findOrFail($receita->saida_item_id)->entradaItens
->each(function ($entradaItem) use ($lotes) {
if ($entradaItem->lote != null) {
$loteExistente = $lotes->first(function ($lote) use ($entradaItem) {
return $lote === "{$entradaItem->lote} ({$entradaItem->validade_lote->format('d/m/Y')})";
});
if (!$loteExistente) {
$lotes->push("{$entradaItem->lote} ({$entradaItem->validade_lote->format('d/m/Y')})");
}
}
});
return [
'receita_item_entrega_id' => $receita->receita_item_entrega_id,
'material' => [
'descricao' => $receita->material_descricao,
],
'lotes' => $lotes,
'dispensado_em' => $receita->dispensado_em,
'usuario_nome' => $receita->usuario_nome,
'prescrito' => $receita->prescrito,
'entregue' => $receita->entregue,
'proxima_retirada' => $receita->proxima_retirada,
'observacao' => $receita->item_observacao,
'data_saida' => $receita->data_saida,
'estornado' => $receita->estornado,
'estorno_salvo' => $receita->estornado,
];
})
->values();
}
private static function getMedicamentosNaoPadronizados($pacienteId)
{
return DB::table('farmacia_medicamento_nao_padronizado')
->select(
'farmacia_medicamento_nao_padronizado.id',
DB::raw("DATE_FORMAT(farmacia_medicamento_nao_padronizado.data_receita, '%d/%m/%Y') as data_receita"),
'cadastro_usuario.id AS usuario_id',
'cadastro_cidadao.nome AS medico_solicitante',
'farmacia_medicamento_nao_padronizado.medicamento_nao_padronizado_id',
'cadastro_medicamento_nao_padronizado.descricao as medicamento',
'farmacia_medicamento_nao_padronizado.quantidade'
)
->join(
'cadastro_medicamento_nao_padronizado',
'cadastro_medicamento_nao_padronizado.id',
'farmacia_medicamento_nao_padronizado.medicamento_nao_padronizado_id'
)
->join(
'cadastro_usuario',
'cadastro_usuario.id',
'farmacia_medicamento_nao_padronizado.usuario_id'
)
->join(
'cadastro_cidadao',
'cadastro_cidadao.id',
'cadastro_usuario.cidadao_id'
)
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'farmacia_medicamento_nao_padronizado.created_centro_custo_id'
)
->where('centro_custo.id', self::getCentroCustoLogado()->id)
->where('paciente_id', $pacienteId)
->get()
->map(function ($item) {
return [
'id' => $item->id,
'data_receita' => $item->data_receita,
'medico_solicitante' => [
'id' => $item->usuario_id,
'cidadao_nome' => $item->medico_solicitante,
],
'medicamento' => [
'id' => $item->medicamento_nao_padronizado_id,
'descricao' => $item->medicamento
],
'quantidade' => $item->quantidade,
'deleted' => false,
'save' => false,
];
});
}
private static function getMedicamentosNaoPadronizadosCadastrados()
{
return DB::table('cadastro_medicamento_nao_padronizado')
->select(
'cadastro_medicamento_nao_padronizado.id',
'cadastro_medicamento_nao_padronizado.descricao',
)
->join(
'cadastro_centro_custo as centro_custo',
'centro_custo.id',
'cadastro_medicamento_nao_padronizado.created_centro_custo_id'
)
->where('centro_custo.id', self::getCentroCustoLogado()->id)
->get();
}
private static function getSolicitacoesMedicamentos($pacienteId)
{
return DB::table('ambulatorio_atendimento_soap_prescricao_medicamento as prescricao')
->join('ambulatorio_atendimento_soap as soap', 'soap.id', 'prescricao.soap_id')
->join('ambulatorio_atendimento as atendimento', 'atendimento.id', 'soap.atendimento_id')
->join('cadastro_lotacao as lotacao', 'lotacao.id', 'prescricao.created_lotacao_id')
->join('cadastro_infraestrutura as infraestrutura', 'infraestrutura.id', 'lotacao.infraestrutura_id')
->join('cadastro_unidade as unidade', 'unidade.id', 'infraestrutura.unidade_id')
->join('cadastro_usuario as usuario', 'usuario.id', 'lotacao.usuario_id')
->join('cadastro_cidadao as cidadao', 'cidadao.id', 'usuario.cidadao_id')
->leftJoin('ambulatorio_atendimento_soap_problema_condicao as problema_condicao', fn ($j) => $j
->on('problema_condicao.soap_id', 'soap.id')
->where('problema_condicao.id', fn ($q) => $q
->select('id')
->from('ambulatorio_atendimento_soap_problema_condicao')
->whereColumn('soap_id', 'soap.id')
->whereNotNull('cid_id')
->limit(1)
)
)
->leftJoin('sigtap.cid as cid', 'cid.id', 'problema_condicao.cid_id')
->where('prescricao.solicitacao_fechada', false)
->where(fn ($q) => $q
->whereExists(fn ($q) => $q
->select(DB::raw(1))
->from('ambulatorio_agendamento as agendamento')
->whereColumn('agendamento.id', 'atendimento.agendamento_id')
->where('agendamento.paciente_id', $pacienteId)
)
->orWhereExists(fn ($q) => $q
->select(DB::raw(1))
->from('ambulatorio_demanda_espontanea as demanda_espontanea')
->whereColumn('demanda_espontanea.id', 'atendimento.demanda_espontanea_id')
->where('demanda_espontanea.paciente_id', $pacienteId)
)
)
->orderBy('prescricao.created_at')
->selectRaw("
prescricao.id as prescricao_id,
prescricao.created_at as data_hora,
IF(infraestrutura.nome IS NULL,
unidade.nome_fantasia,
CONCAT(unidade.nome_fantasia, ' - ', infraestrutura.nome)
) as unidade_infraestrutura,
usuario.id as usuario_id,
cidadao.nome as usuario_nome,
cid.id as cid_id,
cid.codigo as cid_codigo,
cid.nome as cid_nome
")
->get()
->map(function ($solicitacao) {
$solicitacao->descartado = false;
return $solicitacao;
});
}
public static function getItensSolicitacaoMedicamento($prescricaoId)
{
return DB::table('ambulatorio_atendimento_soap_prescricao_medicamento_item as item')
->leftJoin('cadastro_material as material', 'material.id', 'item.material_id')
->leftJoin('cadastro_grupo as grupo', 'grupo.id', 'material.grupo_id')
->leftJoin('cadastro_apresentacao as apresentacao', 'apresentacao.id', 'material.apresentacao_id')
->leftJoin(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'material.apresentacao_unidade_medida_id')
->where('item.prescricao_medicamento_id', $prescricaoId)
->selectRaw("
item.descricao,
item.material_id,
" . MaterialService::getDescricaoCompletaRaw(
'material',
'apresentacao',
'apresentacao_unidade_medida'
) . " as material_descricao_completa,
CAST(material.quantidade AS INTEGER) as material_quantidade,
material.is_programa_remedio_em_casa as material_is_programa_remedio_em_casa,
material.is_alto_custo as material_is_alto_custo,
material.is_acao_judicial as material_is_acao_judicial,
material.is_remume as material_is_remume,
apresentacao_unidade_medida.nome as material_apresentacao_unidade_medida_nome,
grupo.grupo_tipo_id as material_grupo_tipo_id,
item.dose,
item.frequencia_vezes,
item.turno_id,
item.intervalo,
item.intervalo_medida_tempo_id,
item.duracao,
item.duracao_medida_tempo_id,
item.recomendacoes,
item.is_uso_continuo,
item.is_dose_unica
")
->get()
->filter(fn ($i) => is_numeric($i->dose) && is_null($i->frequencia_vezes) && is_null($i->turno_id))
->map(function ($item) {
if (!is_null($item->duracao) && !is_null($item->intervalo_medida_tempo_id)) {
$item->duracao = self::getDuracaoConvertida(
$item->duracao,
$item->duracao_medida_tempo_id,
$item->intervalo_medida_tempo_id
);
}
$item->is_uso_continuo = (bool) $item->is_uso_continuo;
$item->is_dose_unica = (bool) $item->is_dose_unica;
$programa = collect([]);
if ($item->material_grupo_tipo_id === GrupoTipo::MEDICAMENTO) {
if ((bool) $item->material_is_programa_remedio_em_casa) {
$programa->push("Programa remédio em casa");
}
if ((bool) $item->material_is_alto_custo) {
$programa->push("Alto custo");
}
if ((bool) $item->material_is_acao_judicial) {
$programa->push("Ação judicial");
}
if ((bool) $item->material_is_remume) {
$programa->push("REMUME");
}
}
$item->programa = $programa->isNotEmpty() ? implode(', ', $programa->toArray()) : '-';
$estoque = AlmoxarifadoService::getEstoque($item->material_id);
$prescrito = self::getQuantidadePrescrita([
'quantidade' => $item->dose,
'intervalo_tempo' => $item->intervalo,
'intervalo_medida_tempo_id' => $item->intervalo_medida_tempo_id,
'durante_tempo' => $item->duracao,
'material_quantidade' => $item->material_quantidade,
'is_dose_unica' => $item->is_dose_unica,
'is_uso_continuo' => $item->is_uso_continuo,
]);
$entregue = is_null($prescrito)
? 0
: ($prescrito > $estoque['total'] ? $estoque['total'] : $prescrito);
$entradaItensData = AlmoxarifadoService::getEntradaItensData(
$item->material_id,
[
'escolheu_entrada_item_manualmente' => false,
'quantidade' => $entregue,
]
);
$entradaItensAutomaticos = [];
foreach ($entradaItensData as $entradaItemId => $entradaItemData) {
$entradaItensAutomaticos[] = [
'entrada_item_id' => $entradaItemId,
'quantidade_saida' => $entradaItemData['quantidade_saida'],
];
}
$entradaItens = collect($estoque['por_entrada'])
->map(function ($entradaItem) use ($entradaItensAutomaticos) {
$entradaItem['quantidade_saida'] = collect($entradaItensAutomaticos)
->where('entrada_item_id', $entradaItem['entrada_item_id'])
->first()['quantidade_saida'] ?? 0;
return $entradaItem;
});
$item->estoque = $estoque['total'];
$item->prescrito = $prescrito;
$item->entregue = $entregue;
$item->escolheu_entrada_item_manualmente = false;
$item->entrada_itens = $entradaItens;
$item->possui_entrada_com_lote = !is_null($entradaItens->whereNotNull('lote')->first());
unset(
$item->material_grupo_tipo_id,
$item->material_is_programa_remedio_em_casa,
$item->material_is_alto_custo,
$item->material_is_acao_judicial,
$item->material_is_remume
);
return $item;
})
->filter(fn ($i) => !is_null($i->entregue) && $i->entregue > 0)
->values();
}
private static function getDuracaoConvertida($duracao, $duracaoMedidaTempoId, $intervaloMedidaTempoId)
{
$duracao = (int) $duracao;
if (collect([MedidaTempo::MINUTOS, MedidaTempo::HORAS, MedidaTempo::DIAS])->contains($intervaloMedidaTempoId)) {
$duracaoEmDias = null;
if ($duracaoMedidaTempoId === MedidaTempo::DIAS) {
$duracaoEmDias = $duracao;
}
else if ($duracaoMedidaTempoId === MedidaTempo::SEMANAS) {
$duracaoEmDias = $duracao * 7;
}
else if ($duracaoMedidaTempoId === MedidaTempo::MESES) {
$duracaoEmDias = $duracao * 30;
}
return $duracaoEmDias;
}
return $duracao;
}
private static function getQuantidadePrescrita($params)
{
if (!is_numeric($params['quantidade'])) {
return null;
}
$calc = function ($intervaloTempo, $intervaloMedidaTempoId, $duranteTempo) use ($params) {
$quantidade = (int) $params['quantidade'];
$materialQuantidade = (float) $params['material_quantidade'];
$multiplier = self::getUnidadeMedidaTempoMultiplier($intervaloMedidaTempoId);
return ceil($quantidade * $multiplier / $intervaloTempo * $duranteTempo / $materialQuantidade);
};
if ($params['is_dose_unica']) {
if (!is_numeric($params['durante_tempo'])) {
return null;
}
return $calc(1, MedidaTempo::DIAS, (int) $params['durante_tempo']);
}
else if ($params['is_uso_continuo'] || !is_numeric($params['durante_tempo'])) {
$parametrizacaoLimitePrescricaoMedicamento = ParametrizacaoLimitePrescricaoMedicamento::first();
$limiteDias = isset($parametrizacaoLimitePrescricaoMedicamento)
? (int) $parametrizacaoLimitePrescricaoMedicamento->limite_dias
: null;
if (!is_numeric($params['intervalo_tempo'])
|| is_null($params['intervalo_medida_tempo_id'])
|| is_null($limiteDias)
|| $limiteDias === 0
) {
return null;
}
$duranteTempo = self::getDuracaoConvertida($limiteDias, MedidaTempo::DIAS, $params['intervalo_medida_tempo_id']);
return $calc((int) $params['intervalo_tempo'], $params['intervalo_medida_tempo_id'], $duranteTempo);
}
else {
if (!is_numeric($params['intervalo_tempo']) || is_null($params['intervalo_medida_tempo_id'])) {
return null;
}
return $calc((int) $params['intervalo_tempo'], $params['intervalo_medida_tempo_id'], (int) $params['durante_tempo']);
}
}
private static function getUnidadeMedidaTempoMultiplier($intervaloMedidaTempoId)
{
switch ($intervaloMedidaTempoId) {
case MedidaTempo::MINUTOS: return 24 * 60;
case MedidaTempo::HORAS: return 24;
case MedidaTempo::DIAS: return 1;
case MedidaTempo::SEMANAS: return 1;
case MedidaTempo::MESES: return 1;
default: return 0;
}
}
public static function getUltimaRetirada()
{
$params = request()->all();
return DB::table('farmacia_receita_item')
->select(
DB::raw("DATE_FORMAT(farmacia_receita_item.proxima_retirada, '%d/%m/%Y') AS proxima_retirada"),
)
->join(
'farmacia_receita',
'farmacia_receita.id',
'farmacia_receita_item.receita_id'
)
->where('farmacia_receita_item.material_id', $params['material_id'])
->where('farmacia_receita.paciente_id', $params['paciente_id'])
->orderByDesc('farmacia_receita_item.id')
->first();
}
public static function getSupervisor()
{
return [
'supervisores' => Supervisor::where('usuario_id', request()->supervisor_id)
->where('infraestrutura_id', self::getCentroCustoLogado()->infraestrutura_id)
->get()
->map(fn ($supervisor) => [
'id' => $supervisor->id,
'usuario_id' => $supervisor->usuario_id,
]),
];
}
public static function show($id)
{
return Receita::findOrFail($id);
}
public static function store()
{
self::validate();
$receita = null;
DB::transaction(function () use (&$receita) {
$params = request()->all();
if ($params['paciente']['save'] === true) {
$paciente = Paciente::findOrFail($params['paciente_id']);
$paciente->observacao = $params['paciente']['observacao'];
$paciente->save();
}
$params['items'] = collect($params['items']);
if ($params['items']->count() > 0) {
$paciente = Paciente::findOrFail($params['paciente_id']);
$paciente->observacao = $params['paciente']['observacao'];
$paciente->save();
$receita = Receita::create($params)->fresh();
$receitaItemEntregas = collect();
$receita->operadores = collect([]);
$params['items']->map(function ($item) use ($receita, $receitaItemEntregas) {
$item['receita_id'] = $receita->id;
$receitaItem = ReceitaItem::create($item);
$now = Carbon::now();
$dispensadoEm = new Carbon($item['dispensado_em']);
$dispensadoEm->setTime($now->hour, $now->minute, $now->second);
$receita['dispensado_em'] = $dispensadoEm->format('d/m/Y');
$receita['hora_atendimento'] = $dispensadoEm->format('H:i');
$receitaItemEntregaSaved = ReceitaItemEntrega::create([
'receita_item_id' => $receitaItem->id,
'quantidade' => $item['entregue'],
'dispensado_em' => $dispensadoEm,
]);
if (!$receita->operadores->contains($receitaItemEntregaSaved->createdLotacao->usuario->cidadao->nome)) {
$receita->operadores->push($receitaItemEntregaSaved->createdLotacao->usuario->cidadao->nome);
}
$receitaItemEntregas->push([
'receita_item_entrega_id' => $receitaItemEntregaSaved->id,
'material_id' => $receitaItem->material_id,
'quantidade' => $receitaItemEntregaSaved->quantidade,
'escolheu_entrada_item_manualmente' => $item['escolheu_entrada_item_manualmente'],
'entrada_itens' => $item['entrada_itens'],
]);
if ($item['entregue'] < $item['prescrito']) {
ReceitaItemEntrega::create([
'receita_item_id' => $receitaItem->id,
'quantidade' => $item['prescrito'] - $item['entregue'],
'pendente' => true,
]);
}
});
$saidaItens = AlmoxarifadoService::saveSaidaDeDispensacaoDaFarmacia($receitaItemEntregas);
$saidaItens->each(function ($data) {
ReceitaItemEntrega::findOrFail($data['receita_item_entrega_id'])
->update(['saida_item_id' => $data['saida_item_id']]);
});
if (!is_null($params['ambulatorio_prescricao_medicamento_id'])) {
AtendimentoSoapPrescricaoMedicamento::where('id', $params['ambulatorio_prescricao_medicamento_id'])
->update(['solicitacao_fechada' => true]);
}
}
if (count($params['solicitacoes_medicamentos_descartadas']) > 0) {
AtendimentoSoapPrescricaoMedicamento::whereIn('id', $params['solicitacoes_medicamentos_descartadas'])
->update(['solicitacao_fechada' => true]);
}
if (count($params['medicamentos_nao_padronizados']) > 0) {
self::saveMedicamentosNaoPadronizados($params['medicamentos_nao_padronizados']);
}
if (count($params['receitas_pendentes_deleted']) > 0) {
self::destroyItemsPendentesEntrega($params['receitas_pendentes_deleted']);
}
if (count($params['items_entregas_estornados']) > 0) {
self::estornarItensEntregas($params['items_entregas_estornados']);
}
if (isset($params['fila_id'])) {
FilaAtendimentoService::finalize($params['fila_id']);
}
});
return $receita;
}
public static function update($id)
{
self::validate();
$receita = self::show($id);
DB::transaction(function () use (&$receita) {
$params = request()->all();
$params['paciente_id'] = $params['paciente']['id'];
$params['items'] = collect($params['items']);
$paciente = Paciente::findOrFail($params['paciente_id']);
$paciente->observacao = $params['paciente']['observacao'];
$paciente->save();
$receita->observacao = $params['observacao'];
$receitaItemEntregas = collect();
$receita->operadores = collect([]);
$params['items']->map(function ($item) use ($receita, $receitaItemEntregas) {
$receitaItem = ReceitaItem::findOrFail($item['id']);
$receitaItem->observacao = $item['observacao'];
$receitaItem->proxima_retirada = $item['proxima_retirada'];
$receitaItem->save();
$now = Carbon::now();
$dispensadoEm = new Carbon($item['dispensado_em']);
$dispensadoEm->setTime($now->hour, $now->minute, $now->second);
$receita['dispensado_em'] = $dispensadoEm->format('d/m/Y');
$receita['hora_atendimento'] = $dispensadoEm->format('H:i');
$receitaItemEntregaSaved = ReceitaItemEntrega::where('receita_item_id', $receitaItem->id)
->where('pendente', 1)
->first();
$receitaItemEntregaSaved->update([
'quantidade' => $item['entregue'],
'pendente' => false,
'dispensado_em' => $dispensadoEm,
]);
if (!$receita->operadores->contains($receitaItemEntregaSaved->createdLotacao->usuario->cidadao->nome)) {
$receita->operadores->push($receitaItemEntregaSaved->createdLotacao->usuario->cidadao->nome);
}
$receitaItemEntregaSaved->refresh();
$receitaItemEntregas->push([
'receita_item_entrega_id' => $receitaItemEntregaSaved->id,
'material_id' => $receitaItem->material_id,
'quantidade' => $receitaItemEntregaSaved->quantidade,
'escolheu_entrada_item_manualmente' => $item['escolheu_entrada_item_manualmente'],
'entrada_itens' => $item['entrada_itens'],
]);
if ($item['entregue'] < $item['saldo']) {
ReceitaItemEntrega::create([
'receita_item_id' => $receitaItem->id,
'quantidade' => $item['saldo'] - $item['entregue'],
'pendente' => true
]);
}
});
if ($receitaItemEntregas->isNotEmpty()) {
$saidaItens = AlmoxarifadoService::saveSaidaDeDispensacaoDaFarmacia($receitaItemEntregas);
$saidaItens->each(function ($data) {
ReceitaItemEntrega::findOrFail($data['receita_item_entrega_id'])
->update(['saida_item_id' => $data['saida_item_id']]);
});
}
if (count($params['medicamentos_nao_padronizados']) > 0) {
self::saveMedicamentosNaoPadronizados($params['medicamentos_nao_padronizados']);
}
if (count($params['receitas_pendentes_deleted']) > 0) {
self::destroyItemsPendentesEntrega($params['receitas_pendentes_deleted']);
}
if (count($params['items_entregas_estornados']) > 0) {
self::estornarItensEntregas($params['items_entregas_estornados']);
}
});
return $receita;
}
private static function saveMedicamentosNaoPadronizados($medicamentosNaoPadronizados)
{
$medicamentosNaoPadronizados = collect($medicamentosNaoPadronizados);
$medicamentosNaoPadronizados->map(function ($medicamento) {
if (isset($medicamento['deleted']) && $medicamento['deleted']) {
MedicamentoNaoPadronizado::findOrFail($medicamento['id'])->delete();
} else {
if (!is_null($medicamento['id'])) {
$medicFind = MedicamentoNaoPadronizado::findOrFail($medicamento['id']);
$medicFind->fill($medicamento);
$medicFind->save();
} else {
$medic = new MedicamentoNaoPadronizado;
MedicamentoNaoPadronizado::create($medic->fill($medicamento)->toArray());
}
}
});
}
private static function destroyItemsPendentesEntrega($items)
{
$items = collect($items);
$items->map(function ($item) {
ReceitaItemEntrega::where('receita_item_id', $item['id'])
->where('pendente', 1)
->delete();
});
}
private static function estornarItensEntregas($itensEntregasEstornados)
{
foreach ($itensEntregasEstornados as $itemEntregaId) {
$entrega = ReceitaItemEntrega::findOrFail($itemEntregaId);
EstornoDispensacaoService::estornar($entrega);
}
}
public static function validate()
{
$params = request()->all();
$rules = [
'ambulatorio_prescricao_medicamento_id' => [
'nullable',
'integer',
],
'usuario_id' => [
'nullable',
'integer',
Rule::requiredIf(fn () => count($params['items'])),
],
'data_receita' => [
'nullable',
'date_format:Y-m-d',
'before_or_equal:now',
Rule::requiredIf(fn () => count($params['items'])),
],
'numero_notificacao' => [
'nullable',
'string',
'max:8'
],
'cid_id' => [
'nullable',
'integer'
],
'is_receita_sus' => [
'required',
'boolean'
],
'is_remedio_em_casa' => [
'required',
'boolean'
],
'observacao' => [
'nullable',
'string',
'between:3,300'
],
'items' => [
'nullable',
'array'
],
'items.*.receita_id' => [
'nullable',
'integer',
],
'items.*.material_id' => [
'required',
'integer'
],
'dispensado_em' => [
'nullable',
'date_format:Y-m-d H:i',
'before_or_equal:now',
],
'items.*.quantidade' => [
'nullable',
'numeric',
'min:0.01',
'required_if:farmacia_parametrizacao_posologia.is_obrigatorio,true',
],
'items.*.intervalo_tempo' => [
'nullable',
'integer',
'required_if:farmacia_parametrizacao_posologia.is_obrigatorio,true',
],
'items.*.intervalo_medida_tempo_id' => [
'nullable',
'integer',
'required_if:farmacia_parametrizacao_posologia.is_obrigatorio,true',
],
'items.*.durante_tempo' => [
'nullable',
'integer'
],
'items.*.prescrito' => [
'nullable',
'numeric'
],
'items.*.proxima_retirada' => [
'required',
'date_format:Y-m-d',
],
'items.*.observacao' => [
'nullable',
'string',
'between:3,300'
],
'items.*.retiradas' => [
'nullable',
'array'
],
'items.*.entregas.*.receita_item_id' => [
'required',
'integer'
],
'items.*.entregas.*.quantidade' => [
'required',
'integer'
]
];
$messages = [
'items.*.intervalo_tempo.integer' => 'O campo "intervalo de tempo" deve ser um número inteiro.'
];
request()->validate($rules, $messages);
}
public static function getReceitaDispensada($receitaId, $items = [])
{
$receita = DB::table('farmacia_receita')
->select(
'farmacia_receita.id',
DB::raw("
DATE_FORMAT(
(
SELECT MAX(frie.dispensado_em) ultima_entrega
FROM farmacia_receita_item_entrega frie
JOIN farmacia_receita_item fri ON fri.id = frie.receita_item_id
WHERE fri.receita_id = farmacia_receita.id
AND frie.pendente = 0
AND frie.estornado = 0
), '%d/%m/%Y %H:%i'
) AS dispensado_em
"),
'farmacia_receita.is_remedio_em_casa',
'cidadao_paciente.nome AS nome_paciente',
'cidadao_paciente.nome_social AS nome_social_paciente',
'cidadao_paciente.preferencia_nome_id',
'cidadao_paciente.data_nascimento AS data_nascimento_paciente',
'cadastro_paciente.prontuario AS prontuario_paciente',
'cidadao_medico_solicitante.nome AS nome_medico_solicitante',
'cadastro_logradouro_tipo.descricao AS tipo_logradouro_descricao',
'cadastro_logradouro.nome AS logradouro_nome',
'cadastro_logradouro.cep AS logradouro_cep',
DB::raw("COALESCE(cadastro_endereco.numero, 'S/N') AS endereco_numero"),
'cadastro_bairro.nome AS endereco_bairro_nome',
'intranet.cadastro_municipio.nome AS endereco_municipio_nome',
'intranet.cadastro_estado.uf AS endereco_uf',
'unidade_referencia.nome_fantasia AS paciente_unidade_referencia'
)
->join(
'cadastro_paciente',
'cadastro_paciente.id',
'farmacia_receita.paciente_id'
)
->join(
'cadastro_cidadao AS cidadao_paciente',
'cidadao_paciente.id',
'cadastro_paciente.cidadao_id'
)
->join(
'cadastro_lotacao AS lotacao_usuario',
'lotacao_usuario.id',
'farmacia_receita.created_lotacao_id',
)
->join(
'cadastro_usuario AS usuario_medico_solicitante',
'usuario_medico_solicitante.id',
'farmacia_receita.usuario_id'
)
->join(
'cadastro_cidadao AS cidadao_medico_solicitante',
'cidadao_medico_solicitante.id',
'usuario_medico_solicitante.cidadao_id'
)
->leftJoin(
'cadastro_unidade AS unidade_referencia',
'unidade_referencia.id',
'cadastro_paciente.unidade_id',
)
->leftJoin('cadastro_domicilio', 'cadastro_domicilio.id', 'cidadao_paciente.domicilio_id')
->leftJoin('cadastro_endereco', 'cadastro_endereco.id', 'cadastro_domicilio.endereco_id')
->leftJoin('cadastro_logradouro', 'cadastro_logradouro.id', 'cadastro_endereco.logradouro_id')
->leftJoin('cadastro_logradouro_tipo', 'cadastro_logradouro_tipo.id', 'cadastro_logradouro.tipo_id')
->leftJoin('cadastro_bairro', 'cadastro_bairro.id', 'cadastro_logradouro.bairro_id')
->leftJoin('intranet.cadastro_municipio', 'cadastro_municipio.id', 'cadastro_logradouro.municipio_id')
->leftJoin('intranet.cadastro_estado', 'cadastro_estado.id', 'cadastro_municipio.estado_id')
->where('farmacia_receita.id', $receitaId)
->first();
$receita->itens = self::getReceitaDispensadaItem($receitaId, $items);
$receita->operadores = collect([]);
$receita->itens->map(function ($item) use (&$receita) {
if (!$receita->operadores->contains($item->nome_usuario)) {
$receita->operadores->push($item->nome_usuario);
}
});
return $receita;
}
public static function printReceitaDispensada($receitaId, $items = [])
{
$receita = DB::table('farmacia_receita')
->select(
'farmacia_receita.id',
DB::raw("
DATE_FORMAT(
(
SELECT MAX(frie.dispensado_em) ultima_entrega
FROM farmacia_receita_item_entrega frie
JOIN farmacia_receita_item fri ON fri.id = frie.receita_item_id
WHERE fri.receita_id = farmacia_receita.id
AND frie.pendente = 0
AND frie.estornado = 0
), '%d/%m/%Y %H:%i'
) AS dispensado_em
"),
'farmacia_receita.is_remedio_em_casa',
'cidadao_paciente.nome AS nome_paciente',
'cidadao_paciente.nome_social AS nome_social_paciente',
'cidadao_paciente.preferencia_nome_id',
'cidadao_paciente.data_nascimento AS data_nascimento_paciente',
'cadastro_paciente.prontuario AS prontuario_paciente',
'cidadao_medico_solicitante.nome AS nome_medico_solicitante',
'cadastro_logradouro_tipo.descricao AS tipo_logradouro_descricao',
'cadastro_logradouro.nome AS logradouro_nome',
'cadastro_logradouro.cep AS logradouro_cep',
DB::raw("COALESCE(cadastro_endereco.numero, 'S/N') AS endereco_numero"),
'cadastro_bairro.nome AS endereco_bairro_nome',
'intranet.cadastro_municipio.nome AS endereco_municipio_nome',
'intranet.cadastro_estado.uf AS endereco_uf',
DB::raw("
COALESCE(
unidade_referencia.nome_fantasia,
'NÃO INFORMADO NO CADASTRO DO PACIENTE'
) AS paciente_unidade_referencia
")
)
->join(
'cadastro_paciente',
'cadastro_paciente.id',
'farmacia_receita.paciente_id'
)
->join(
'cadastro_cidadao AS cidadao_paciente',
'cidadao_paciente.id',
'cadastro_paciente.cidadao_id'
)
->join(
'cadastro_lotacao AS lotacao_usuario',
'lotacao_usuario.id',
'farmacia_receita.created_lotacao_id',
)
->join(
'cadastro_usuario AS usuario_medico_solicitante',
'usuario_medico_solicitante.id',
'farmacia_receita.usuario_id'
)
->join(
'cadastro_cidadao AS cidadao_medico_solicitante',
'cidadao_medico_solicitante.id',
'usuario_medico_solicitante.cidadao_id'
)
->leftJoin(
'cadastro_unidade AS unidade_referencia',
'unidade_referencia.id',
'cadastro_paciente.unidade_id',
)
->leftJoin('cadastro_domicilio', 'cadastro_domicilio.id', 'cidadao_paciente.domicilio_id')
->leftJoin('cadastro_endereco', 'cadastro_endereco.id', 'cadastro_domicilio.endereco_id')
->leftJoin('cadastro_logradouro', 'cadastro_logradouro.id', 'cadastro_endereco.logradouro_id')
->leftJoin('cadastro_logradouro_tipo', 'cadastro_logradouro_tipo.id', 'cadastro_logradouro.tipo_id')
->leftJoin('cadastro_bairro', 'cadastro_bairro.id', 'cadastro_logradouro.bairro_id')
->leftJoin('intranet.cadastro_municipio', 'cadastro_municipio.id', 'cadastro_logradouro.municipio_id')
->leftJoin('intranet.cadastro_estado', 'cadastro_estado.id', 'cadastro_municipio.estado_id')
->where('farmacia_receita.id', $receitaId)
->first();
$receita->itens = self::getReceitaDispensadaItem($receitaId, $items);
$receita->operadores = collect([]);
$receita->itens->map(function ($item) use (&$receita) {
if (!$receita->operadores->contains($item->nome_usuario)) {
$receita->operadores->push($item->nome_usuario);
}
});
$receita->data_nascimento_paciente =
(new Carbon($receita->data_nascimento_paciente))->format('d/m/Y');
$receita->itens->map(function ($item) {
$item->vencimento_receita = $item->proxima_retirada
? self::getVencimentoReceita($item)->format('d/m/Y')
: null;
$item->proxima_retirada = $item->proxima_retirada
? (new Carbon($item->proxima_retirada))->format('d/m/Y')
: null;
$item->material = [
'descricao_completa' => $item->material_descricao
];
$entradaItens = SaidaItem::findOrFail($item->saida_item_id)->entradaItens->map(function ($entradaItem) {
return [
'lote' => $entradaItem->lote,
'validade_lote' => $entradaItem->validade_lote ? $entradaItem->validade_lote->format('d/m/Y') : null,
'quantidade_saida' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida,
];
});
$entradaItens = $entradaItens->groupBy(function ($item) {
return $item['lote'] . '_' . $item['validade_lote'];
});
$entradaItens = $entradaItens->values()->map(function ($item) {
$totalQuantidadeSaida = $item->sum('quantidade_saida');
$firstItem = $item->first();
return [
'lote' => $firstItem['lote'],
'validade_lote' => $firstItem['validade_lote'],
'quantidade_saida' => $totalQuantidadeSaida,
];
});
$item->entradaItens = $entradaItens->all();
});
$dispensadoEm = Carbon::createFromFormat('d/m/Y H:i', $receita->dispensado_em);
$receita->dispensado_em = $dispensadoEm->format('d/m/Y');
$receita->hora_atendimento = $dispensadoEm->format('H:i');
return $receita;
}
public static function printReceitaHistorico($id)
{
$query = DB::table('farmacia_historico_dispensacao_v1')->find($id);
$data_hora_dispensacao = Carbon::parse($query->data_hora_dispensacao);
return [
'operadores' => [],
'nome_medico_solicitante' => $query->nome_medico,
'itens' => [
[
'material' => [
'descricao_completa' => $query->nome_medicamento
],
'prescrito' => $query->quantidade_receita,
'proxima_retirada' => Carbon::parse($query->data_proxima_retirada)->format('d/m/Y'),
'entrada_itens' => [
[
'lote' => $query->lote,
'dispensado_em' => Carbon::parse($query->data_hora_dispensacao)->format('d/m/Y H:i'),
'quantidade_saida' => $query->quantidade,
'observacao' => $query->observacao,
]
]
]
],
'dispensado_em' => $data_hora_dispensacao->format('d/m/Y'),
'hora_atendimento' => $data_hora_dispensacao->format('H:i')
];
}
private static function getReceitaDispensadaItem($receitaId, $items = [])
{
$receitaItem = DB::table('farmacia_receita_item')
->select(
'farmacia_receita_item.id AS item_id',
'farmacia_receita_item.durante_tempo',
'farmacia_receita_item.intervalo_medida_tempo_id',
'farmacia_receita_item.intervalo_tempo',
'farmacia_receita_item.material_id',
'farmacia_receita_item.observacao AS item_observacao',
'farmacia_receita_item.prescrito',
'farmacia_receita_item.proxima_retirada',
'farmacia_receita_item.quantidade',
'farmacia_receita_item.receita_id',
'farmacia_receita_item_entrega.quantidade AS retirado',
'farmacia_receita_item_entrega.saida_item_id',
'cidadao_usuario.nome AS nome_usuario',
DB::raw("
" . MaterialService::getDescricaoCompletaRaw(
'cadastro_material',
'cadastro_apresentacao',
'apresentacao_unidade_medida'
) . " AS material_descricao,
DATE_FORMAT(farmacia_receita_item_entrega.dispensado_em, '%d/%m/%Y %H:%i') AS dispensado_em,
(
SELECT frie.quantidade
FROM farmacia_receita_item_entrega frie
WHERE frie.receita_item_id = farmacia_receita_item.id
AND frie.pendente = 1
) AS saldo
"),
)
->join(
'cadastro_material',
'cadastro_material.id',
'farmacia_receita_item.material_id'
)
->join(
'cadastro_apresentacao',
'cadastro_apresentacao.id',
'cadastro_material.apresentacao_id'
)
->join(
'farmacia_receita_item_entrega',
'farmacia_receita_item_entrega.receita_item_id',
'farmacia_receita_item.id'
)
->join(
'cadastro_lotacao',
'cadastro_lotacao.id',
'farmacia_receita_item_entrega.created_lotacao_id'
)
->join(
'cadastro_usuario AS usuario_lotacao',
'usuario_lotacao.id',
'cadastro_lotacao.usuario_id'
)
->join(
'cadastro_cidadao AS cidadao_usuario',
'cidadao_usuario.id',
'usuario_lotacao.cidadao_id'
)
->leftJoin(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'cadastro_material.apresentacao_unidade_medida_id'
)
->where('farmacia_receita_item.receita_id', $receitaId)
->where('farmacia_receita_item_entrega.pendente', false)
->where('farmacia_receita_item_entrega.estornado', false);
$items = collect($items);
if ($items->count() > 0) {
$receitaItem->whereIn('farmacia_receita_item_entrega.receita_item_id', $items->pluck('id')->toArray());
}
return $receitaItem->get();
}
private static function getCentroCustoLogado()
{
return CentroCusto::findOrFail(auth()->payload()->get('centro_custo_id'));
}
public static function getDataProximaRetirada($fromDate, $item)
{
$fromDate->setTime(0, 0, 0);
$getMultiplierUnidadeTempoDurante = function ($unidadesMedidaTempoDurante) {
switch ($unidadesMedidaTempoDurante) {
case MedidaTempo::SEMANAS: return 7;
case MedidaTempo::MESES: return 30;
default: return 1;
}
};
$getUnidadeMedidaTempoMultiplier = function ($intervaloMedidaTempoId) {
switch ($intervaloMedidaTempoId) {
case MedidaTempo::MINUTOS: return 24 * 60;
case MedidaTempo::HORAS: return 24;
case MedidaTempo::DIAS: return 1;
case MedidaTempo::SEMANAS: return 1;
case MedidaTempo::MESES: return 1;
default: return 0;
}
};
$multiplier = $getMultiplierUnidadeTempoDurante($item['intervalo_medida_tempo_id']);
if ($item['continuo']) {
$unidadeMedidaTempoMultiplier = $getUnidadeMedidaTempoMultiplier($item['intervalo_medida_tempo_id']);
$entregueXmaterialQuantidade = $item['entregue'] * $item['material']['quantidade'];
$days = $entregueXmaterialQuantidade / (($unidadeMedidaTempoMultiplier / $item['intervalo_tempo']) * $item['quantidade']);
return $fromDate->addDays(round($days));
}
if ($item['durante_tempo']) {
$days = $multiplier * $item['durante_tempo'];
if ($item['prescrito'] != $item['entregue']) {
$diff = $item['prescrito'] / $item['entregue'];
$days = $item['durante_tempo'] / $diff;
}
return $fromDate->addDays(round($days));
}
return null;
}
private static function getPermissoesAtualizacaoCadastroPaciente()
{
$parametrizacao = CnsService::getParametrizacao();
if (!is_null($parametrizacao)) {
$lotacao = self::getCurrentLotacao();
return DB::table('cadastro_parametrizacao_permissao_usuario')
->select([
'municipe',
'provisorio',
'outro_municipio',
])
->where('infraestrutura_id', $lotacao->infraestrutura_id)
->where('usuario_id', $lotacao->usuario_id)
->get()
->first();
}
return null;
}
private static function getLastUpdated($paciente)
{
$updatedPaciente = $paciente->updated_at;
$updatedCidadao = $paciente->cidadao->updated_at ?? null;
if ($updatedPaciente && $updatedCidadao) {
$data = $updatedPaciente > $updatedCidadao
? $updatedPaciente
: $updatedCidadao;
} else {
$data = $updatedPaciente ?? $updatedCidadao;
}
return $data ? $data->format('d/m/Y') : null;
}
}