1008 lines
30 KiB
PHP
1008 lines
30 KiB
PHP
<?php
|
|
|
|
namespace App\Services\WebService\Ambulatorio\Cliente;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use GuzzleHttp\Client;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use App\Models\Ambulatorio\Atendimento;
|
|
use App\Models\Ambulatorio\Jornada;
|
|
use App\Models\Ambulatorio\AtendimentoSoap;
|
|
use App\Enums\Ambulatorio\FeridaExsudato;
|
|
use App\Enums\Ambulatorio\LocalAnatomico;
|
|
use App\Enums\Ambulatorio\LocalAnatomicoRegiao;
|
|
use App\Exceptions\WebService\Ambulatorio\ConectaSus\LocalAnatomicoRegiaoNotFoundException;
|
|
use App\Exceptions\WebService\Ambulatorio\ConectaSus\LocalAnatomicoRegiaoInativoException;
|
|
use App\Exceptions\WebService\Ambulatorio\ConectaSus\LocalAnatomicoInconsistenteException;
|
|
use App\Exceptions\WebService\Ambulatorio\ConectaSus\LocalAnatomicoAusenteException;
|
|
use App\Exceptions\WebService\Ambulatorio\ConectaSus\FeridaNotFoundException;
|
|
use App\Exceptions\WebService\Ambulatorio\ConectaSus\LocalAnatomicoNotFoundException;
|
|
|
|
class AtendimentoSafecareService
|
|
{
|
|
public static function salvarPayloadPartner(array $data, string $customer, ?string $idempotencyKey = null): array
|
|
{
|
|
$idempotencyKey = $idempotencyKey ?: self::chaveDeterministica($data, $customer);
|
|
|
|
return DB::transaction(function () use ($data, $customer, $idempotencyKey) {
|
|
|
|
$idempotency = self::garantirIdempotencia($idempotencyKey, $customer, $data);
|
|
|
|
if ($idempotency['replayed'] === true) {
|
|
|
|
return $idempotency['response'];
|
|
}
|
|
|
|
$meta = $data['metaDataConectaSus'];
|
|
|
|
$atendimento = Atendimento::query()
|
|
->where('agendamento_id', $meta['agendamento_id'])
|
|
->firstOrFail();
|
|
|
|
$jornada = Jornada::query()
|
|
->where('id', $meta['jornada_id'])
|
|
->firstOrFail();
|
|
|
|
$soapId = self::ensureSoap($atendimento->id, $jornada->id);
|
|
|
|
if (!empty($data['antropometria']) && is_array($data['antropometria'])) {
|
|
|
|
self::upsertAntropometria($atendimento->id, $soapId, $data['antropometria']);
|
|
}
|
|
|
|
if (!empty($data['sinais_vitais']) && is_array($data['sinais_vitais'])) {
|
|
|
|
self::upsertSinaisVitais($atendimento->id, $soapId, $data['sinais_vitais']);
|
|
}
|
|
|
|
if (!empty($data['feridas'])) {
|
|
|
|
if (isset($data['feridas'][0]) && is_array($data['feridas'][0])) {
|
|
|
|
foreach ($data['feridas'] as $indice => $ferida) {
|
|
|
|
if (is_array($ferida)) {
|
|
|
|
self::upsertFeridas($soapId, $ferida, $indice);
|
|
}
|
|
}
|
|
} elseif (is_array($data['feridas'])) {
|
|
|
|
self::upsertFeridas($soapId, $data['feridas'], 0);
|
|
}
|
|
}
|
|
|
|
$response = [
|
|
'updated' => true,
|
|
'atendimento_id' => $atendimento->id,
|
|
'soap_id' => $soapId,
|
|
'idempotency_key' => $idempotencyKey,
|
|
];
|
|
|
|
self::salvarRespostaIdempotencia($idempotencyKey, $customer, $response);
|
|
|
|
return $response;
|
|
});
|
|
}
|
|
|
|
private static function ensureSoap(int $atendimentoId, int $jornadaId): int
|
|
{
|
|
$dado = DB::table('ambulatorio_atendimento_soap')
|
|
->where('atendimento_id', $atendimentoId)
|
|
->first();
|
|
|
|
if ($dado) {
|
|
|
|
return (int) $dado->id;
|
|
}
|
|
|
|
$soapId = DB::table('ambulatorio_atendimento_soap')->insertGetId([
|
|
'atendimento_id' => $atendimentoId,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
'created_centro_custo_id' => self::getCentroCusto($jornadaId),
|
|
'created_lotacao_id' => self::getLotacao($jornadaId)
|
|
]);
|
|
|
|
return (int) $soapId;
|
|
}
|
|
|
|
private static function getCentroCusto(int $jornadaId): int
|
|
{
|
|
return DB::table('ambulatorio_jornada')
|
|
->where('id', $jornadaId)
|
|
->value('created_centro_custo_id');
|
|
}
|
|
|
|
private static function getLotacao(int $jornadaId): int
|
|
{
|
|
return DB::table('ambulatorio_jornada')
|
|
->where('id', $jornadaId)
|
|
->value('created_lotacao_id');
|
|
}
|
|
|
|
private static function upsertAntropometria(int $atendimentoId, int $soapId, array $ant): void
|
|
{
|
|
$update = ['updated_at' => now()];
|
|
|
|
if (array_key_exists('peso', $ant)) {
|
|
|
|
$update['peso'] = $ant['peso'];
|
|
}
|
|
|
|
if (array_key_exists('altura', $ant)) {
|
|
|
|
$update['altura'] = $ant['altura'];
|
|
}
|
|
|
|
if (array_key_exists('perimetro_cefalico', $ant)) {
|
|
|
|
$update['perimetro_cefalico'] = $ant['perimetro_cefalico'];
|
|
}
|
|
|
|
if (array_key_exists('circunferencia_abdominal', $ant)) {
|
|
|
|
$update['circunferencia_abdominal'] = $ant['circunferencia_abdominal'];
|
|
}
|
|
|
|
if (array_key_exists('perimetro_panturrilha', $ant)) {
|
|
|
|
$update['perimetro_panturrilha'] = $ant['perimetro_panturrilha'];
|
|
}
|
|
|
|
if (array_key_exists('comprimento_pe_direito', $ant)) {
|
|
|
|
$update['comprimento_pe_direito'] = $ant['comprimento_pe_direito'];
|
|
}
|
|
|
|
if (array_key_exists('largura_pe_direito', $ant)) {
|
|
|
|
$update['largura_pe_direito'] = $ant['largura_pe_direito'];
|
|
}
|
|
|
|
if (array_key_exists('circunferencia_pe_direito', $ant)) {
|
|
|
|
$update['circunferencia_pe_direito'] = $ant['circunferencia_pe_direito'];
|
|
}
|
|
|
|
if (array_key_exists('comprimento_pe_esquerdo', $ant)) {
|
|
|
|
$update['comprimento_pe_esquerdo'] = $ant['comprimento_pe_esquerdo'];
|
|
}
|
|
|
|
if (array_key_exists('largura_pe_esquerdo', $ant)) {
|
|
|
|
$update['largura_pe_esquerdo'] = $ant['largura_pe_esquerdo'];
|
|
}
|
|
|
|
if (array_key_exists('circunferencia_pe_esquerdo', $ant)) {
|
|
|
|
$update['circunferencia_pe_esquerdo'] = $ant['circunferencia_pe_esquerdo'];
|
|
}
|
|
|
|
if (count($update) === 1) {
|
|
|
|
return;
|
|
}
|
|
|
|
$exists = DB::table('ambulatorio_atendimento_antropometria')
|
|
->where('atendimento_id', $atendimentoId)
|
|
->where('soap_id', $soapId)
|
|
->exists();
|
|
|
|
if ($exists) {
|
|
|
|
DB::table('ambulatorio_atendimento_antropometria')
|
|
->where('atendimento_id', $atendimentoId)
|
|
->where('soap_id', $soapId)
|
|
->update($update);
|
|
|
|
return;
|
|
}
|
|
|
|
$insert = array_merge($update, [
|
|
'atendimento_id' => $atendimentoId,
|
|
'soap_id' => $soapId,
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
DB::table('ambulatorio_atendimento_antropometria')
|
|
->insert($insert);
|
|
}
|
|
|
|
private static function upsertSinaisVitais(int $atendimentoId, int $soapId, array $sv): void
|
|
{
|
|
$update = ['updated_at' => now()];
|
|
|
|
if (array_key_exists('pressao_arterial', $sv)) {
|
|
|
|
$update['pressao_arterial'] = $sv['pressao_arterial'];
|
|
}
|
|
|
|
if (array_key_exists('frequencia_respiratoria', $sv)) {
|
|
|
|
$update['frequencia_respiratoria'] = $sv['frequencia_respiratoria'];
|
|
}
|
|
|
|
if (array_key_exists('frequencia_cardiaca', $sv)) {
|
|
|
|
$update['frequencia_cardiaca'] = $sv['frequencia_cardiaca'];
|
|
}
|
|
|
|
if (array_key_exists('temperatura', $sv)) {
|
|
|
|
$update['temperatura'] = $sv['temperatura'];
|
|
}
|
|
|
|
if (array_key_exists('saturacao_o2', $sv)) {
|
|
|
|
$update['saturacao_o2'] = $sv['saturacao_o2'];
|
|
}
|
|
|
|
if (count($update) === 1) {
|
|
|
|
return;
|
|
}
|
|
|
|
$exists = DB::table('ambulatorio_atendimento_sinal_vital')
|
|
->where('atendimento_id', $atendimentoId)
|
|
->where('soap_id', $soapId)
|
|
->exists();
|
|
|
|
if ($exists) {
|
|
|
|
DB::table('ambulatorio_atendimento_sinal_vital')
|
|
->where('atendimento_id', $atendimentoId)
|
|
->where('soap_id', $soapId)
|
|
->update($update);
|
|
|
|
return;
|
|
}
|
|
|
|
$insert = array_merge($update, [
|
|
'atendimento_id' => $atendimentoId,
|
|
'soap_id' => $soapId,
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
DB::table('ambulatorio_atendimento_sinal_vital')
|
|
->insert($insert);
|
|
}
|
|
|
|
private static function upsertFeridas(int $soapId, array $fe, int $indice = 0): void
|
|
{
|
|
$update = ['updated_at' => now()];
|
|
|
|
$feridaId = null;
|
|
$identificadorExterno = (string) ($fe['identificador_externo'] ?? '');
|
|
|
|
if (!empty($identificadorExterno)) {
|
|
|
|
$feridaId = self::resolveFeridaId($identificadorExterno);
|
|
}
|
|
|
|
if (!$feridaId) {
|
|
|
|
throw new FeridaNotFoundException($identificadorExterno ?: 'vazio', $indice);
|
|
}
|
|
|
|
$update['ferida_id'] = $feridaId;
|
|
|
|
$paiDescricao = trim((string) ($fe['local_anatomico_descricao'] ?? ''));
|
|
$filhoDescricao = trim((string) ($fe['local_regiao_anatomico_descricao'] ?? ''));
|
|
|
|
$temPai = $paiDescricao !== '';
|
|
$temFilho = $filhoDescricao !== '';
|
|
|
|
if (!$temPai && !$temFilho) {
|
|
|
|
throw new LocalAnatomicoAusenteException($indice);
|
|
}
|
|
|
|
if ($temFilho) {
|
|
|
|
$localIdPreResolve = $temPai ? self::resolveLocalAnatomicoId($paiDescricao) : null;
|
|
|
|
$regiaoRow = self::resolveLocalAnatomicoRegiaoCompleto($filhoDescricao, $localIdPreResolve);
|
|
|
|
if (!$regiaoRow) {
|
|
|
|
throw new LocalAnatomicoRegiaoNotFoundException($filhoDescricao, $indice);
|
|
}
|
|
|
|
if (isset($regiaoRow->ativo) && !$regiaoRow->ativo) {
|
|
|
|
throw new LocalAnatomicoRegiaoInativoException($filhoDescricao, $indice);
|
|
}
|
|
|
|
$regiaoId = (int) $regiaoRow->id;
|
|
$localIdFromRegiao = (int) $regiaoRow->local_anatomico_id;
|
|
|
|
if ($temPai) {
|
|
|
|
$localIdEnviado = $localIdPreResolve;
|
|
|
|
if ($localIdEnviado !== null && $localIdEnviado !== $localIdFromRegiao) {
|
|
|
|
throw new LocalAnatomicoInconsistenteException($paiDescricao, $filhoDescricao, $indice);
|
|
}
|
|
}
|
|
|
|
$update['local_anatomico_id'] = $localIdFromRegiao;
|
|
$update['local_anatomico_regiao_id'] = $regiaoId;
|
|
} else {
|
|
|
|
$localId = self::resolveLocalAnatomicoId($paiDescricao);
|
|
|
|
if (!$localId) {
|
|
|
|
throw new LocalAnatomicoNotFoundException($paiDescricao, $indice);
|
|
}
|
|
|
|
$update['local_anatomico_id'] = $localId;
|
|
|
|
$naoInformadoRow = DB::table('cadastro_local_anatomico_regiao')
|
|
->where('local_anatomico_id', $localId)
|
|
->where('key', 'nao_informado')
|
|
->first();
|
|
|
|
$update['local_anatomico_regiao_id'] = $naoInformadoRow ? (int) $naoInformadoRow->id : null;
|
|
}
|
|
|
|
if (array_key_exists('data_inicio_tratamento', $fe)) {
|
|
|
|
$update['data'] = $fe['data_inicio_tratamento'];
|
|
}
|
|
|
|
if (array_key_exists('ferida_necrose_porcentagem', $fe)) {
|
|
|
|
$necroseId = self::resolveFeridaNecroseId((string) $fe['ferida_necrose_porcentagem']);
|
|
$update['ferida_necrose'] = $necroseId;
|
|
}
|
|
|
|
if (array_key_exists('ferida_exsudato_descricao', $fe)) {
|
|
|
|
$exsudatoId = self::resolveExsudatoId((string) $fe['ferida_exsudato_descricao']);
|
|
$update['ferida_exsudato_id'] = $exsudatoId;
|
|
}
|
|
|
|
if (array_key_exists('status_ferida', $fe)) {
|
|
|
|
$status = mb_strtolower(trim((string) $fe['status_ferida']));
|
|
$update['cicatrizada'] = in_array($status, ['cicatrizada', 'cicatriz', '1', 'true'], true);
|
|
}
|
|
|
|
if (array_key_exists('dor', $fe)) {
|
|
|
|
$update['dor'] = (int) $fe['dor'];
|
|
}
|
|
|
|
if (array_key_exists('comprimento_ferida', $fe)) {
|
|
|
|
$update['comprimento'] = $fe['comprimento_ferida'];
|
|
}
|
|
|
|
if (array_key_exists('largura_ferida', $fe)) {
|
|
|
|
$update['largura'] = $fe['largura_ferida'];
|
|
}
|
|
|
|
if (array_key_exists('profundidade_ferida', $fe)) {
|
|
|
|
$update['profundidade'] = $fe['profundidade_ferida'];
|
|
}
|
|
|
|
$query = DB::table('ambulatorio_atendimento_soap_ferida')
|
|
->where('soap_id', $soapId);
|
|
|
|
if (isset($update['ferida_id'])) {
|
|
|
|
$query->where('ferida_id', $update['ferida_id']);
|
|
}
|
|
|
|
if (isset($update['local_anatomico_id'])) {
|
|
|
|
$query->where('local_anatomico_id', $update['local_anatomico_id']);
|
|
}
|
|
|
|
if (isset($update['local_anatomico_regiao_id'])) {
|
|
|
|
$query->where('local_anatomico_regiao_id', $update['local_anatomico_regiao_id']);
|
|
}
|
|
|
|
$exists = $query->exists();
|
|
|
|
if ($exists) {
|
|
|
|
$query->update($update);
|
|
return;
|
|
}
|
|
|
|
$insert = array_merge($update, [
|
|
'soap_id' => $soapId,
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
$soapFeridaId = (int) DB::table('ambulatorio_atendimento_soap_ferida')->insertGetId($insert);
|
|
|
|
self::persistFeridaImages($soapFeridaId, [
|
|
$fe['foto_ferida'] ?? null,
|
|
$fe['foto_ferida_limpa'] ?? null,
|
|
$fe['foto_curativo'] ?? null,
|
|
$fe['foto_ferida_evolucao'] ?? null,
|
|
]);
|
|
|
|
$procedimentos = self::resolveProcedimentosFromFerida($feridaId);
|
|
|
|
if (!empty($procedimentos)) {
|
|
|
|
$soap = AtendimentoSoap::find($soapId);
|
|
|
|
$atendimentoId = data_get($soap, 'atendimento_id');
|
|
|
|
if ($atendimentoId === null) {
|
|
|
|
$atendimentoId = (int) DB::table('ambulatorio_atendimento_soap')
|
|
->where('id', $soapId)
|
|
->value('atendimento_id');
|
|
}
|
|
|
|
$ocupacaoId = data_get($soap, 'atendimento.ocupacao.id') ?? data_get($soap, 'createdLotacao.ocupacao_id');
|
|
$especialidadeId = data_get($soap, 'atendimento.especialidade.id');
|
|
$usuarioId = data_get($soap, 'atendimento.usuario.id') ?? data_get($soap, 'createdLotacao.usuario_id');
|
|
|
|
foreach ($procedimentos as $proc) {
|
|
|
|
$procedimentoId = $proc['procedimento_id'];
|
|
$cidId = $proc['cid_id'];
|
|
|
|
$atendimentoProcedimentoId = DB::table('ambulatorio_atendimento_procedimento')
|
|
->where('atendimento_id', $atendimentoId)
|
|
->where('procedimento_id', $procedimentoId)
|
|
->where('soap_id', $soapId)
|
|
->orderByDesc('id')
|
|
->value('id');
|
|
|
|
if (!$atendimentoProcedimentoId) {
|
|
|
|
$atendimentoProcedimentoId = DB::table('ambulatorio_atendimento_procedimento')->insertGetId([
|
|
'atendimento_id' => $atendimentoId,
|
|
'procedimento_id' => $procedimentoId,
|
|
'soap_id' => $soapId,
|
|
'cid_id' => $cidId,
|
|
'quantidade' => 1,
|
|
'automatico' => false,
|
|
'ocupacao_id' => $ocupacaoId,
|
|
'especialidade_id' => $especialidadeId,
|
|
'usuario_id' => $usuarioId,
|
|
'created_lotacao_id' => data_get($soap, 'created_lotacao_id'),
|
|
'created_centro_custo_id' => data_get($soap, 'created_centro_custo_id'),
|
|
'updated_lotacao_id' => data_get($soap, 'updated_lotacao_id') ?? data_get($soap, 'created_lotacao_id'),
|
|
'updated_centro_custo_id' => data_get($soap, 'updated_centro_custo_id') ?? data_get($soap, 'created_centro_custo_id'),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
DB::table('ambulatorio_atendimento_soap_procedimento_clinico')->insert([
|
|
'soap_id' => $soapId,
|
|
'atendimento_procedimento_id' => $atendimentoProcedimentoId,
|
|
'created_lotacao_id' => data_get($soap, 'created_lotacao_id'),
|
|
'created_centro_custo_id' => data_get($soap, 'created_centro_custo_id'),
|
|
'updated_lotacao_id' => data_get($soap, 'updated_lotacao_id') ?? data_get($soap, 'created_lotacao_id'),
|
|
'updated_centro_custo_id' => data_get($soap, 'updated_centro_custo_id') ?? data_get($soap, 'created_centro_custo_id'),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
|
|
$existsLink = DB::table('ambulatorio_atendimento_soap_ferida_procedimento')
|
|
->where('soap_ferida_id', $soapFeridaId)
|
|
->where('atendimento_procedimento_id', $atendimentoProcedimentoId)
|
|
->exists();
|
|
|
|
if (!$existsLink) {
|
|
DB::table('ambulatorio_atendimento_soap_ferida_procedimento')->insert([
|
|
'soap_id' => $soapId,
|
|
'soap_ferida_id' => $soapFeridaId,
|
|
'atendimento_procedimento_id' => $atendimentoProcedimentoId,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function persistFeridaImages(int $soapFeridaId, array $arquivos): void
|
|
{
|
|
foreach ($arquivos as $arquivo) {
|
|
|
|
if (!is_string($arquivo)) {
|
|
|
|
continue;
|
|
}
|
|
|
|
$arquivo = trim($arquivo);
|
|
|
|
if ($arquivo === '') {
|
|
|
|
continue;
|
|
}
|
|
|
|
if (self::isHttpUrl($arquivo)) {
|
|
|
|
$saved = self::downloadAndStoreImage($arquivo);
|
|
|
|
if ($saved === null) {
|
|
|
|
continue;
|
|
}
|
|
|
|
$arquivo = $saved;
|
|
}
|
|
|
|
$exists = DB::table('ambulatorio_atendimento_soap_ferida_imagem')
|
|
->where('soap_ferida_id', $soapFeridaId)
|
|
->where('arquivo', $arquivo)
|
|
->exists();
|
|
|
|
if ($exists) {
|
|
|
|
continue;
|
|
}
|
|
|
|
DB::table('ambulatorio_atendimento_soap_ferida_imagem')->insert([
|
|
'soap_ferida_id' => $soapFeridaId,
|
|
'arquivo' => $arquivo,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
private static function isHttpUrl(?string $string): bool
|
|
{
|
|
if (!is_string($string)) {
|
|
|
|
return false;
|
|
}
|
|
|
|
$string = trim($string);
|
|
|
|
if ($string === '') {
|
|
|
|
return false;
|
|
}
|
|
|
|
return (bool) filter_var($string, FILTER_VALIDATE_URL) && preg_match('#^https?://#i', $string) === 1;
|
|
}
|
|
|
|
private static function guessExtensionFromUrl(string $url): ?string
|
|
{
|
|
$path = parse_url($url, PHP_URL_PATH) ?: '';
|
|
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
|
|
|
if (in_array($ext, ['jpg', 'jpeg', 'png', 'webp', 'gif'], true)) {
|
|
|
|
return $ext === 'jpeg' ? 'jpg' : $ext;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static function getExtensionFromContentType(?string $contentType): ?string
|
|
{
|
|
$map = [
|
|
'image/jpeg' => 'jpg',
|
|
'image/jpg' => 'jpg',
|
|
'image/png' => 'png',
|
|
'image/webp' => 'webp',
|
|
'image/gif' => 'gif',
|
|
];
|
|
|
|
$ct = $contentType ? strtolower(trim($contentType)) : null;
|
|
|
|
return $ct && isset($map[$ct]) ? $map[$ct] : null;
|
|
}
|
|
|
|
private static function buildFeridasBasePath(): string
|
|
{
|
|
$db = app('config')->get('database.default');
|
|
|
|
return 'ambulatorio' . DIRECTORY_SEPARATOR . 'feridas' . DIRECTORY_SEPARATOR . $db;
|
|
}
|
|
|
|
private static function downloadAndStoreImage(string $url, int $timeoutSeconds = 15, int $maxBytes = 10_000_000): ?string
|
|
{
|
|
$permitidos = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp', 'image/gif'];
|
|
|
|
try {
|
|
$cliente = new Client([
|
|
'timeout' => $timeoutSeconds,
|
|
'allow_redirects' => true,
|
|
'http_errors' => false,
|
|
'headers' => [
|
|
'User-Agent' => 'SafeCareImageFetcher/1.0',
|
|
],
|
|
]);
|
|
|
|
$response = $cliente->get($url, ['stream' => true]);
|
|
|
|
$code = $response->getStatusCode();
|
|
|
|
if ($code !== 200) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$contentType = strtolower(trim($response->getHeaderLine('content-type')));
|
|
$extensao = self::getExtensionFromContentType($contentType);
|
|
|
|
if (!$extensao) {
|
|
|
|
$extensao = self::guessExtensionFromUrl($url);
|
|
|
|
if (!$extensao) {
|
|
|
|
$extensao = 'jpg';
|
|
}
|
|
}
|
|
|
|
if ($contentType !== '' && !in_array($contentType, $permitidos, true)) {
|
|
|
|
if (!in_array($extensao, ['jpg', 'png', 'webp', 'gif'], true)) {
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
$body = $response->getBody();
|
|
$buffer = '';
|
|
$read = 0;
|
|
$chunkSize = 131072;
|
|
|
|
while (!$body->eof()) {
|
|
|
|
$chunk = $body->read($chunkSize);
|
|
|
|
if ($chunk === '') {
|
|
|
|
break;
|
|
}
|
|
|
|
$read += strlen($chunk);
|
|
|
|
if ($read > $maxBytes) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$buffer .= $chunk;
|
|
}
|
|
|
|
if ($buffer === '') {
|
|
|
|
return null;
|
|
}
|
|
|
|
$nomeArquivo = Str::uuid()->toString() . '.' . $extensao;
|
|
$caminhoBase = self::buildFeridasBasePath();
|
|
$caminhoCompleto = $caminhoBase . DIRECTORY_SEPARATOR . $nomeArquivo;
|
|
|
|
$ok = Storage::put($caminhoCompleto, $buffer);
|
|
|
|
if (!$ok) {
|
|
|
|
return null;
|
|
}
|
|
|
|
return $nomeArquivo;
|
|
} catch (\Throwable $e) {
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static function resolveFeridaId(?string $identificadorExterno): ?int
|
|
{
|
|
if (empty($identificadorExterno)) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$row = DB::table('cadastro_ferida')
|
|
->where('identificador_externo', $identificadorExterno)
|
|
->first();
|
|
|
|
return $row ? (int) $row->id : null;
|
|
}
|
|
|
|
private static function resolveLocalAnatomicoId(?string $descricao): ?int
|
|
{
|
|
if ($descricao === null) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$id = LocalAnatomico::fromDescricao($descricao);
|
|
|
|
if ($id !== null) {
|
|
|
|
return $id;
|
|
}
|
|
|
|
$localNormalizado = mb_strtolower(trim($descricao));
|
|
|
|
$row = DB::table('cadastro_local_anatomico')
|
|
->whereRaw('LOWER(descricao) = ?', [$localNormalizado])
|
|
->first();
|
|
|
|
if ($row) {
|
|
|
|
return (int) $row->id;
|
|
}
|
|
|
|
$row = DB::table('cadastro_local_anatomico')
|
|
->where('descricao', 'like', '%' . $descricao . '%')
|
|
->first();
|
|
|
|
return $row ? (int) $row->id : null;
|
|
}
|
|
|
|
private static function resolveLocalAnatomicoRegiaoId(?string $descricaoOuKey, ?int $localAnatomicoId = null): ?int
|
|
{
|
|
return self::attemptResolveRegion($descricaoOuKey, $localAnatomicoId);
|
|
}
|
|
|
|
private static function attemptResolveRegion(?string $descricaoOuKey, ?int $localAnatomicoId): ?int
|
|
{
|
|
if ($descricaoOuKey === null) {
|
|
|
|
return null;
|
|
}
|
|
|
|
if ($descricaoOuKey) {
|
|
|
|
$id = LocalAnatomicoRegiao::fromKey($descricaoOuKey, $localAnatomicoId);
|
|
|
|
if ($id !== null) {
|
|
|
|
return $id;
|
|
}
|
|
}
|
|
|
|
$id = LocalAnatomicoRegiao::fromDescricao($descricaoOuKey, $localAnatomicoId);
|
|
|
|
if ($id !== null) {
|
|
|
|
return $id;
|
|
}
|
|
|
|
$norm = LocalAnatomicoRegiao::normalize($descricaoOuKey);
|
|
|
|
$query = DB::table('cadastro_local_anatomico_regiao')
|
|
->whereRaw('LOWER(descricao) = ?', [$norm]);
|
|
|
|
if ($localAnatomicoId !== null) {
|
|
|
|
$query->where('local_anatomico_id', $localAnatomicoId);
|
|
}
|
|
|
|
$row = $query->first(['id']);
|
|
|
|
if ($row) {
|
|
|
|
return (int) $row->id;
|
|
}
|
|
|
|
$like = DB::table('cadastro_local_anatomico_regiao')
|
|
->where('descricao', 'like', '%' . $descricaoOuKey . '%');
|
|
|
|
if ($localAnatomicoId !== null) {
|
|
|
|
$like->where('local_anatomico_id', $localAnatomicoId);
|
|
}
|
|
|
|
$rowLike = $like->first(['id']);
|
|
|
|
return $rowLike ? (int) $rowLike->id : null;
|
|
}
|
|
|
|
private static function resolveLocalAnatomicoRegiaoCompleto(?string $descricaoOuKey, ?int $localAnatomicoId = null): ?object
|
|
{
|
|
if ($descricaoOuKey === null) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$cols = ['id', 'local_anatomico_id', 'ativo'];
|
|
|
|
$id = LocalAnatomicoRegiao::fromKey($descricaoOuKey, $localAnatomicoId);
|
|
|
|
if ($id !== null) {
|
|
|
|
return DB::table('cadastro_local_anatomico_regiao')
|
|
->where('id', $id)
|
|
->first($cols);
|
|
}
|
|
|
|
$id = LocalAnatomicoRegiao::fromDescricao($descricaoOuKey, $localAnatomicoId);
|
|
|
|
if ($id !== null) {
|
|
|
|
return DB::table('cadastro_local_anatomico_regiao')
|
|
->where('id', $id)
|
|
->first($cols);
|
|
}
|
|
|
|
$norm = LocalAnatomicoRegiao::normalize($descricaoOuKey);
|
|
|
|
$exactQuery = DB::table('cadastro_local_anatomico_regiao')
|
|
->whereRaw('LOWER(descricao) = ?', [$norm]);
|
|
|
|
if ($localAnatomicoId !== null) {
|
|
|
|
$exactQuery->where('local_anatomico_id', $localAnatomicoId);
|
|
}
|
|
|
|
$row = $exactQuery->first($cols);
|
|
|
|
if ($row) {
|
|
|
|
return $row;
|
|
}
|
|
|
|
$likeQuery = DB::table('cadastro_local_anatomico_regiao')
|
|
->where('descricao', 'like', '%' . $descricaoOuKey . '%');
|
|
|
|
if ($localAnatomicoId !== null) {
|
|
|
|
$likeQuery->where('local_anatomico_id', $localAnatomicoId);
|
|
}
|
|
|
|
return $likeQuery->first($cols);
|
|
}
|
|
|
|
private static function resolveFeridaNecroseId(?string $valor): ?int
|
|
{
|
|
if ($valor === null) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$raw = trim(mb_strtolower($valor));
|
|
|
|
$necroseNormalizada = str_replace(' ', '', $raw);
|
|
|
|
if (preg_match('/^\d{1,3}$/', $necroseNormalizada) === 1) {
|
|
|
|
$necroseNormalizada = $necroseNormalizada . '%';
|
|
}
|
|
|
|
$permitidos = ['0%', '20%', '40%', '60%', '80%', '100%'];
|
|
|
|
if (!in_array($necroseNormalizada, $permitidos, true)) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$id = DB::table('cadastro_ferida_necrose')
|
|
->whereRaw('LOWER(descricao) = ?', [$necroseNormalizada])
|
|
->value('id');
|
|
|
|
return $id ? (int) $id : null;
|
|
}
|
|
|
|
private static function resolveExsudatoId(?string $descricao): ?int
|
|
{
|
|
if ($descricao === null) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$id = FeridaExsudato::fromDescricao($descricao);
|
|
|
|
if ($id !== null) {
|
|
|
|
return $id;
|
|
}
|
|
|
|
$exsudatoNormalizado = mb_strtolower(trim($descricao));
|
|
$row = DB::table('cadastro_ferida_exsudato')
|
|
->whereRaw('LOWER(descricao) = ?', [$exsudatoNormalizado])
|
|
->first();
|
|
|
|
if ($row) {
|
|
|
|
return (int) $row->id;
|
|
}
|
|
|
|
$row = DB::table('cadastro_ferida_exsudato')
|
|
->where('descricao', 'like', '%' . $descricao . '%')
|
|
->first();
|
|
|
|
return $row ? (int) $row->id : null;
|
|
}
|
|
|
|
private static function resolveProcedimentosFromFerida(?int $feridaId): array
|
|
{
|
|
$items = [];
|
|
|
|
if ($feridaId) {
|
|
|
|
$associacoes = DB::table('cadastro_ferida_procedimento')
|
|
->where('ferida_id', $feridaId)
|
|
->get();
|
|
|
|
foreach ($associacoes as $assoc) {
|
|
|
|
if (!empty($assoc->procedimento_id)) {
|
|
|
|
$items[] = [
|
|
'procedimento_id' => (int) $assoc->procedimento_id,
|
|
'cid_id' => !empty($assoc->cid_id) ? (int) $assoc->cid_id : null,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $items;
|
|
}
|
|
|
|
private static function chaveDeterministica(array $data, string $customer): string
|
|
{
|
|
$meta = $data['metaDataConectaSus'] ?? [];
|
|
|
|
$payloadHash = hash('sha256', json_encode($data));
|
|
|
|
$seed = json_encode([
|
|
'customer' => $customer,
|
|
'agendamento' => $meta['agendamento_id'] ?? null,
|
|
'payload_hash' => $payloadHash,
|
|
]);
|
|
|
|
return hash('sha256', $seed);
|
|
}
|
|
|
|
private static function garantirIdempotencia(string $key, string $customer, array $payload): array
|
|
{
|
|
$existing = DB::table('idempotencies_safecare')
|
|
->where('key', $key)
|
|
->where('customer', $customer)
|
|
->first();
|
|
|
|
if ($existing && !empty($existing->response_json)) {
|
|
|
|
return [
|
|
'replayed' => true,
|
|
'response' => json_decode($existing->response_json, true),
|
|
];
|
|
}
|
|
|
|
if (!$existing) {
|
|
|
|
DB::table('idempotencies_safecare')->insert([
|
|
'key' => $key,
|
|
'customer' => $customer,
|
|
'request_hash' => hash('sha256', json_encode($payload)),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
|
|
return ['replayed' => false];
|
|
}
|
|
|
|
private static function salvarRespostaIdempotencia(string $key, string $customer, array $response): void
|
|
{
|
|
DB::table('idempotencies_safecare')
|
|
->where('key', $key)
|
|
->where('customer', $customer)
|
|
->update([
|
|
'response_json' => json_encode($response),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
}
|