435 lines
22 KiB
PHP
435 lines
22 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Integracao\Bnafar;
|
|
|
|
use App\Enums\Almoxarifado\SaidaTipo;
|
|
use App\Enums\Cadastro\Fabricante\Tipo as FabricanteTipo;
|
|
use App\Enums\Integracao\Bnafar\BnafarOperacaoTipo;
|
|
use App\Enums\Integracao\Bnafar\BnafarProcessamentoStatus;
|
|
use App\Enums\Integracao\Bnafar\BnafarSaidaTipo;
|
|
use App\Enums\Integracao\Bnafar\BnafarServicoTipo;
|
|
use App\Models\Integracao\Bnafar\Protocolo;
|
|
use App\Models\Integracao\Bnafar\ProtocoloResposta;
|
|
use App\Models\Integracao\Bnafar\Saida;
|
|
use App\Models\Integracao\Bnafar\SaidaItem;
|
|
use App\Services\Integracao\BnafarService;
|
|
use App\Services\Service;
|
|
use App\Services\Telegram\TelegramService;
|
|
use Exception;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class SaidaService extends Service
|
|
{
|
|
private const SAIDAS_POR_PROTOCOLO = 1000;
|
|
private const ITENS_POR_SAIDA = 60;
|
|
|
|
public static function store()
|
|
{
|
|
$saidas = self::getAlmoxarifadoSaidas();
|
|
|
|
if (sizeof($saidas) > 0) {
|
|
$protocoloId = Protocolo::create([
|
|
'servico_tipo_id' => BnafarServicoTipo::SAIDA,
|
|
'operacao_tipo_id' => BnafarOperacaoTipo::OPERACAO_INCLUSAO_REGISTRO,
|
|
])->id;
|
|
}
|
|
|
|
foreach ($saidas as $saida) {
|
|
$saidaId = DB::table('integracao_bnafar_saida')
|
|
->where('almoxarifado_saida_id', $saida->almoxarifado_saida_id)
|
|
->whereRaw('
|
|
(
|
|
SELECT COUNT(*)
|
|
FROM integracao_bnafar_saida_item
|
|
WHERE integracao_bnafar_saida_item.saida_id = integracao_bnafar_saida.id
|
|
) < ' . self::ITENS_POR_SAIDA . '
|
|
')
|
|
->first()->id ?? null;
|
|
|
|
if (is_null($saidaId)) {
|
|
$protocoloId = DB::table('integracao_bnafar_protocolo')
|
|
->where('id', $protocoloId)
|
|
->whereRaw('
|
|
(
|
|
SELECT COUNT(*)
|
|
FROM integracao_bnafar_saida
|
|
WHERE integracao_bnafar_saida.protocolo_id = integracao_bnafar_protocolo.id
|
|
) < ' . self::SAIDAS_POR_PROTOCOLO . '
|
|
')
|
|
->first()->id ?? null;
|
|
|
|
if (is_null($protocoloId)) {
|
|
$protocoloId = Protocolo::create([
|
|
'servico_tipo_id' => BnafarServicoTipo::SAIDA,
|
|
'operacao_tipo_id' => BnafarOperacaoTipo::OPERACAO_INCLUSAO_REGISTRO,
|
|
])->id;
|
|
}
|
|
|
|
$saidaId = Saida::create([
|
|
'protocolo_id' => $protocoloId,
|
|
'saida_tipo_id' => self::getSaidaTipo($saida->saida_tipo_id),
|
|
'almoxarifado_saida_id' => $saida->almoxarifado_saida_id,
|
|
'centro_custo_id' => $saida->centro_custo_id,
|
|
'data_saida' => $saida->data_saida,
|
|
'centro_custo_destino_id' => $saida->centro_custo_destino_id,
|
|
])->id;
|
|
}
|
|
|
|
SaidaItem::create([
|
|
'saida_id' => $saidaId,
|
|
'almoxarifado_saida_item_id' => $saida->almoxarifado_saida_item_id,
|
|
'material_id' => $saida->material_id,
|
|
'fabricante_id' => $saida->fabricante_id,
|
|
'integracao_bnafar_medicamento_id' => $saida->integracao_bnafar_medicamento_id,
|
|
'lote' => $saida->lote,
|
|
'data_validade' => $saida->data_validade,
|
|
'quantidade' => $saida->quantidade,
|
|
'valor_unitario' => $saida->valor_unitario,
|
|
]);
|
|
}
|
|
}
|
|
|
|
public static function post($cliente, $token, $ibge)
|
|
{
|
|
$protocolos = self::getSaidas();
|
|
|
|
foreach ($protocolos as $protocolo) {
|
|
try {
|
|
$response = BnafarService::post(['action' => 'saida-lote', 'token' => $token, 'ibge' => $ibge], $protocolo['saidas']);
|
|
|
|
if (isset($response['protocolo'])) {
|
|
Protocolo::where('id', $protocolo['id'])->update([
|
|
'processamento_status_id' => $response['situacao'],
|
|
'protocolo' => $response['protocolo'],
|
|
'data_protocolo' => $response['dataProtocolo'],
|
|
]);
|
|
} else {
|
|
Protocolo::where('id', $protocolo['id'])->update(['processamento_status_id' => BnafarProcessamentoStatus::ERRO_INTERNO_SERVIDOR]);
|
|
|
|
ProtocoloResposta::create([
|
|
'protocolo_id' => $protocolo['id'],
|
|
'resposta' => json_encode($response->json()),
|
|
]);
|
|
}
|
|
} catch (Exception $error) {
|
|
Log::channel('integracao-bnafar')->error('Erro ao executar o comando', [
|
|
'cliente' => $cliente,
|
|
'origem' => 'PosicaoEstoqueService',
|
|
'erro' => $error->getMessage(),
|
|
]);
|
|
|
|
if (env('APP_ENV') === 'production') {
|
|
TelegramService::send('<strong>Integração BNAFAR (' . $cliente . '):</strong> (Erro ao executar o comando: EnviarPosicaoEstoqueCommand).');
|
|
}
|
|
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function check($cliente, $token, $ibge)
|
|
{
|
|
Protocolo::whereNull('protocolo')->delete();
|
|
|
|
$protocolos = self::getProtocolos();
|
|
|
|
foreach ($protocolos as $protocolo) {
|
|
try {
|
|
$response = BnafarService::getDetalheProcessamento($token, $ibge, $protocolo->protocolo);
|
|
|
|
if (isset($response['protocolo'])) {
|
|
Protocolo::where('id', $protocolo->id)->update(['processamento_status_id' => $response['protocolo']['situacao']]);
|
|
}
|
|
|
|
$resposta = BnafarService::getInconsistencias($token, $ibge, $protocolo->protocolo);
|
|
|
|
if (!is_null($resposta)) {
|
|
ProtocoloResposta::create([
|
|
'protocolo_id' => $protocolo->id,
|
|
'resposta' => $resposta,
|
|
]);
|
|
|
|
self::salvarInconsistenciasItens($resposta);
|
|
} else {
|
|
ProtocoloResposta::where('protocolo_id', $protocolo->id)->delete();
|
|
}
|
|
|
|
if (isset($response['itensProcessados'])) {
|
|
foreach ($response['itensProcessados'] as $itemProcessado) {
|
|
Saida::where('id', $itemProcessado['codigoOrigem'])->update([
|
|
'codigo_registro' => isset($itemProcessado['codigoBnafar']) && $itemProcessado['codigoBnafar'] > 0 ? $itemProcessado['codigoBnafar'] : null,
|
|
'processado_sucesso' => $itemProcessado['sucesso'],
|
|
]);
|
|
}
|
|
}
|
|
} catch (Exception $error) {
|
|
Log::channel('integracao-bnafar')->error('Erro ao executar o comando', [
|
|
'cliente' => $cliente,
|
|
'origem' => 'PosicaoEstoqueService',
|
|
'erro' => $error->getMessage(),
|
|
]);
|
|
|
|
if (env('APP_ENV') === 'production') {
|
|
TelegramService::send('<strong>Integração BNAFAR (' . $cliente . '):</strong> (Erro ao executar o comando: EnviarPosicaoEstoqueCommand).');
|
|
}
|
|
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function salvarInconsistenciasItens($resposta)
|
|
{
|
|
collect(json_decode($resposta, true))
|
|
->pluck('inconsistencias')
|
|
->filter()
|
|
->flatten(1)
|
|
->groupBy('codigoOrigem')
|
|
->each(function ($inconsistencias, $codigoOrigem) {
|
|
$mensagem = $inconsistencias
|
|
->pluck('mensagem')
|
|
->map(fn ($mensagem) => BnafarService::formatarMensagem($mensagem))
|
|
->filter()
|
|
->unique()
|
|
->implode(' ');
|
|
|
|
SaidaItem::where('id', $codigoOrigem)->update(['mensagem' => $mensagem]);
|
|
});
|
|
}
|
|
|
|
private static function getSaidas()
|
|
{
|
|
return DB::table('integracao_bnafar_protocolo')
|
|
->select('id')
|
|
->where('servico_tipo_id', BnafarServicoTipo::SAIDA)
|
|
->whereNull('integracao_bnafar_protocolo.processamento_status_id')
|
|
->get()
|
|
->map(function($protocolo) {
|
|
$saidas = DB::table('integracao_bnafar_saida')
|
|
->select([
|
|
'cadastro_unidade.cnes AS cnes',
|
|
'cadastro_setor.id AS setor_tipo_id',
|
|
'integracao_bnafar_saida.id AS codigo_origem',
|
|
DB::raw("DATE_FORMAT(integracao_bnafar_saida.data_saida, '%Y-%m-%d') AS data_saida"),
|
|
'cadastro_unidade_destino.cnes AS estabelecimento_destino',
|
|
'integracao_bnafar_saida_tipo.codigo AS tipo_saida',
|
|
])
|
|
->join('cadastro_centro_custo', 'cadastro_centro_custo.id', 'integracao_bnafar_saida.centro_custo_id')
|
|
->join('cadastro_setor', 'cadastro_setor.id', 'cadastro_centro_custo.setor_id')
|
|
->join('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_centro_custo.infraestrutura_id')
|
|
->join('cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id')
|
|
->join('cadastro_centro_custo AS cadastro_centro_custo_destino', 'cadastro_centro_custo_destino.id', 'integracao_bnafar_saida.centro_custo_destino_id')
|
|
->join('cadastro_infraestrutura AS cadastro_infraestrutura_destino', 'cadastro_infraestrutura_destino.id', 'cadastro_centro_custo_destino.infraestrutura_id')
|
|
->join('cadastro_unidade AS cadastro_unidade_destino', 'cadastro_unidade_destino.id', 'cadastro_infraestrutura_destino.unidade_id')
|
|
->join('integracao_bnafar_saida_tipo', 'integracao_bnafar_saida_tipo.id', 'integracao_bnafar_saida.saida_tipo_id')
|
|
->where('integracao_bnafar_saida.protocolo_id', $protocolo->id)
|
|
->where('cadastro_unidade_destino.cnes', '!=', null)
|
|
->where(function($query) {
|
|
$query
|
|
->whereNull('integracao_bnafar_saida.processado_sucesso')
|
|
->orWhere('integracao_bnafar_saida.processado_sucesso', false);
|
|
})
|
|
->get()
|
|
->map(function($saida) {
|
|
$itens = DB::table('integracao_bnafar_saida_item')
|
|
->select([
|
|
'integracao_bnafar_saida_item.id AS codigo_origem',
|
|
'cadastro_material_bnafar.codigo AS numero',
|
|
'cadastro_material_bnafar.tipo AS tipo_produto',
|
|
'integracao_bnafar_saida_item.lote',
|
|
DB::raw("DATE_FORMAT(integracao_bnafar_saida_item.data_validade, '%Y-%m-%d') AS data_validade"),
|
|
'cadastro_fabricante.tipo_id AS tipo_fabricante',
|
|
'cadastro_fabricante.cnpj AS cnpj_fabricante',
|
|
'cadastro_fabricante.nome AS nome_fabricante',
|
|
'integracao_bnafar_medicamento.codigo AS integracao_bnafar_medicamento_codigo',
|
|
'integracao_bnafar_saida_item.quantidade',
|
|
'integracao_bnafar_saida_item.valor_unitario',
|
|
])
|
|
->join('cadastro_material', 'cadastro_material.id', 'integracao_bnafar_saida_item.material_id')
|
|
->join('cadastro_material_bnafar', 'cadastro_material_bnafar.id', 'cadastro_material.material_bnafar_id')
|
|
->join('cadastro_fabricante', 'cadastro_fabricante.id', 'integracao_bnafar_saida_item.fabricante_id')
|
|
->leftJoin('integracao_bnafar_medicamento', 'integracao_bnafar_medicamento.id', 'integracao_bnafar_saida_item.integracao_bnafar_medicamento_id')
|
|
->where('integracao_bnafar_saida_item.saida_id', $saida->codigo_origem)
|
|
->get()
|
|
->map(function($item) {
|
|
return [
|
|
'codigoOrigem' => $item->codigo_origem,
|
|
'numero' => $item->numero,
|
|
'terminologia' => $item->integracao_bnafar_medicamento_codigo ? 'OBM' : 'CATMAT',
|
|
'codigoAmpp' => $item->integracao_bnafar_medicamento_codigo,
|
|
'tipoProduto' => $item->tipo_produto,
|
|
'lote' => $item->lote,
|
|
'dataValidade' => $item->data_validade,
|
|
'cnpjFabricante' => $item->tipo_fabricante === FabricanteTipo::NACIONAL ? $item->cnpj_fabricante : null,
|
|
'nomeFabricanteInternacional' => $item->tipo_fabricante === FabricanteTipo::INTERNACIONAL ? $item->nome_fabricante : null,
|
|
'quantidade' => $item->quantidade,
|
|
'valorUnitario' => $item->valor_unitario,
|
|
];
|
|
})
|
|
->toArray();
|
|
|
|
return [
|
|
'estabelecimento' => [
|
|
'cnes' => $saida->cnes,
|
|
'tipo' => BnafarService::getEstabelecimentoTipo($saida->setor_tipo_id),
|
|
],
|
|
'caracterizacao' => [
|
|
'codigoOrigem' => $saida->codigo_origem,
|
|
'dataSaida' => $saida->data_saida,
|
|
'estabelecimentoDestino' => $saida->estabelecimento_destino,
|
|
'tipoSaida' => $saida->tipo_saida,
|
|
],
|
|
'itens' => $itens,
|
|
];
|
|
})
|
|
->toArray();
|
|
|
|
return [
|
|
'id' => $protocolo->id,
|
|
'saidas' => $saidas,
|
|
];
|
|
})
|
|
->toArray();
|
|
}
|
|
|
|
private static function getProtocolos()
|
|
{
|
|
return DB::table('integracao_bnafar_protocolo')
|
|
->select([
|
|
'id',
|
|
'protocolo',
|
|
])
|
|
->where('servico_tipo_id', BnafarServicoTipo::SAIDA)
|
|
->where('processamento_status_id', '!=', BnafarProcessamentoStatus::PROCESSAMENTO_FINALIZADO_SEM_INCONSISTENCIA)
|
|
->whereNotNull('processamento_status_id')
|
|
->get();
|
|
}
|
|
|
|
private static function getAlmoxarifadoSaidas()
|
|
{
|
|
return DB::table('almoxarifado_saida_item')
|
|
->select([
|
|
'almoxarifado_saida.tipo_id AS saida_tipo_id',
|
|
'almoxarifado_saida.id AS almoxarifado_saida_id',
|
|
'almoxarifado_saida.centro_custo_id',
|
|
DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%Y-%m-%d') AS data_saida"),
|
|
'almoxarifado_saida_item.id AS almoxarifado_saida_item_id',
|
|
'almoxarifado_saida_item.material_id',
|
|
'almoxarifado_entrada_item.fabricante_id',
|
|
'almoxarifado_entrada_item.integracao_bnafar_medicamento_id',
|
|
'almoxarifado_entrada_item.lote AS lote',
|
|
DB::raw("DATE_FORMAT(almoxarifado_entrada_item.validade_lote, '%Y-%m-%d') AS data_validade"),
|
|
'almoxarifado_saida_item_entrada_item.quantidade_saida AS quantidade',
|
|
'almoxarifado_entrada_item.valor_unitario',
|
|
DB::raw("
|
|
(
|
|
CASE almoxarifado_saida.tipo_id WHEN " . SaidaTipo::MANUAL . " THEN
|
|
(
|
|
select centro_custo_id
|
|
from almoxarifado_saida_requisicao
|
|
where almoxarifado_saida_requisicao.saida_id = almoxarifado_saida.id
|
|
)
|
|
WHEN " . SaidaTipo::REQUISICAO . " THEN
|
|
(
|
|
select almoxarifado_requisicao.created_centro_custo_id
|
|
from almoxarifado_requisicao_resposta_item
|
|
inner join almoxarifado_requisicao_item
|
|
on almoxarifado_requisicao_item.id = almoxarifado_requisicao_resposta_item.requisicao_item_id
|
|
inner join almoxarifado_requisicao
|
|
on almoxarifado_requisicao.id = almoxarifado_requisicao_item.requisicao_id
|
|
where almoxarifado_requisicao_resposta_item.saida_item_id = almoxarifado_saida_item.id
|
|
)
|
|
WHEN " . SaidaTipo::INVENTARIO . " THEN
|
|
almoxarifado_saida.centro_custo_id
|
|
WHEN " . SaidaTipo::ESTORNO . " THEN
|
|
almoxarifado_saida.centro_custo_id
|
|
WHEN " . SaidaTipo::BAIXA . " THEN
|
|
almoxarifado_saida.centro_custo_id
|
|
WHEN " . SaidaTipo::TRANSFERENCIA . " THEN
|
|
(
|
|
select almoxarifado_saida_transferencia.centro_custo_id
|
|
from almoxarifado_saida_transferencia
|
|
where almoxarifado_saida_transferencia.saida_id = almoxarifado_saida.id
|
|
)
|
|
END
|
|
) AS centro_custo_destino_id
|
|
")
|
|
])
|
|
->join('almoxarifado_saida', 'almoxarifado_saida.id', 'almoxarifado_saida_item.saida_id')
|
|
->join('almoxarifado_saida_item_entrada_item', 'almoxarifado_saida_item_entrada_item.saida_item_id', 'almoxarifado_saida_item.id')
|
|
->join('almoxarifado_entrada_item', 'almoxarifado_entrada_item.id', 'almoxarifado_saida_item_entrada_item.entrada_item_id')
|
|
->where('almoxarifado_saida.finalizada', true)
|
|
->where('almoxarifado_saida.tipo_id', '<>', SaidaTipo::DISPENSACAO_FARMACIA)
|
|
->whereRaw("CAST(almoxarifado_saida.created_at AS DATE) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)")
|
|
->whereNotNull('almoxarifado_entrada_item.fabricante_id')
|
|
->whereNotNull('almoxarifado_entrada_item.lote')
|
|
->where(DB::raw('ROUND(almoxarifado_entrada_item.valor_unitario, 2)'), '>', 0)
|
|
->whereRaw("
|
|
(
|
|
CASE almoxarifado_saida.tipo_id WHEN " . SaidaTipo::MANUAL . " THEN
|
|
(
|
|
select centro_custo_id
|
|
from almoxarifado_saida_requisicao
|
|
where almoxarifado_saida_requisicao.saida_id = almoxarifado_saida.id
|
|
)
|
|
WHEN " . SaidaTipo::REQUISICAO . " THEN
|
|
(
|
|
select almoxarifado_requisicao.created_centro_custo_id
|
|
from almoxarifado_requisicao_resposta_item
|
|
inner join almoxarifado_requisicao_item
|
|
on almoxarifado_requisicao_item.id = almoxarifado_requisicao_resposta_item.requisicao_item_id
|
|
inner join almoxarifado_requisicao
|
|
on almoxarifado_requisicao.id = almoxarifado_requisicao_item.requisicao_id
|
|
where almoxarifado_requisicao_resposta_item.saida_item_id = almoxarifado_saida_item.id
|
|
)
|
|
WHEN " . SaidaTipo::INVENTARIO . " THEN
|
|
almoxarifado_saida.centro_custo_id
|
|
WHEN " . SaidaTipo::ESTORNO . " THEN
|
|
almoxarifado_saida.centro_custo_id
|
|
WHEN " . SaidaTipo::BAIXA . " THEN
|
|
almoxarifado_saida.centro_custo_id
|
|
WHEN " . SaidaTipo::TRANSFERENCIA . " THEN
|
|
(
|
|
select almoxarifado_saida_transferencia.centro_custo_id
|
|
from almoxarifado_saida_transferencia
|
|
where almoxarifado_saida_transferencia.saida_id = almoxarifado_saida.id
|
|
)
|
|
END
|
|
) IS NOT NULL
|
|
")
|
|
->whereExists(fn ($q) => $q
|
|
->select(DB::raw(1))
|
|
->from('cadastro_material')
|
|
->join('cadastro_material_bnafar', 'cadastro_material_bnafar.id', 'cadastro_material.material_bnafar_id')
|
|
->whereColumn('cadastro_material.id', 'almoxarifado_saida_item.material_id')
|
|
)
|
|
->whereNotExists(function ($query) {
|
|
$query->select(DB::raw(1))
|
|
->from('integracao_bnafar_saida')
|
|
->whereColumn('integracao_bnafar_saida.almoxarifado_saida_id', 'almoxarifado_saida.id');
|
|
})
|
|
->get();
|
|
}
|
|
|
|
private static function getSaidaTipo($saidaTipoId)
|
|
{
|
|
$saidaTipo = null;
|
|
|
|
if ($saidaTipoId === SaidaTipo::INVENTARIO) {
|
|
$saidaTipo = BnafarSaidaTipo::SAIDA_POR_AJUSTE_ESTOQUE;
|
|
}
|
|
else if ($saidaTipoId === SaidaTipo::ESTORNO) {
|
|
$saidaTipo = BnafarSaidaTipo::DEVOLUCAO_DE_ENTRADA_PRODUTO;
|
|
}
|
|
else if ($saidaTipoId === SaidaTipo::BAIXA) {
|
|
$saidaTipo = BnafarSaidaTipo::SAIDA_POR_PERDA;
|
|
}
|
|
else if ($saidaTipoId === SaidaTipo::MANUAL || $saidaTipoId === SaidaTipo::REQUISICAO || $saidaTipoId === SaidaTipo::TRANSFERENCIA) {
|
|
$saidaTipo = BnafarSaidaTipo::SAIDA_POR_TRANSFERENCIA_REMANEJAMENTO;
|
|
}
|
|
|
|
return $saidaTipo;
|
|
}
|
|
}
|