Files
rkm-conectasus-ci-sandbox/api/app/Services/WebService/Ambulatorio/Cliente/AtendimentoSafecareService.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

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(),
]);
}
}