Files
SGF/app/Services/Sgc/ThreeWayMatchService.php
T
2026-11-11 09:00:17 +02:00

98 lines
3.1 KiB
PHP

<?php
namespace App\Services\Sgc;
use App\Models\Sgc\Fatura;
use App\Models\Sgc\OrdemCompra;
use App\Models\Sgc\Recebimento;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ThreeWayMatchService
{
private const TOLERANCIA_PERCENTUAL = 0.01; // 1%
private const TOLERANCIA_VALOR = 50.00; // 50 MT
/**
* Executa o 3-Way Match: OC + Recebimento + Fatura
*/
public function executarMatch(Fatura $fatura): array
{
$oc = $fatura->ordemCompra;
$recebimentos = $oc->recebimentos;
// Calcular total recebido
$valorTotalRecebido = $recebimentos->sum('valor_recebido');
$valorFatura = $fatura->valor_fatura;
$valorOC = $oc->valor_comprometido;
// Verificar divergências
$divergenciaOC = abs($valorFatura - $valorOC);
$divergenciaRecebimento = abs($valorFatura - $valorTotalRecebido);
// Aplicar tolerâncias
$toleranciaOC = max($valorOC * self::TOLERANCIA_PERCENTUAL, self::TOLERANCIA_VALOR);
$toleranciaRecebimento = max($valorTotalRecebido * self::TOLERANCIA_PERCENTUAL, self::TOLERANCIA_VALOR);
$matchOC = $divergenciaOC <= $toleranciaOC;
$matchRecebimento = $divergenciaRecebimento <= $toleranciaRecebimento;
// Determinar status
$status = 'Conforme';
$motivo = null;
if (!$matchOC && !$matchRecebimento) {
$status = 'Com Excecao';
$motivo = "Divergência com OC ({$divergenciaOC} MT) e Recebimento ({$divergenciaRecebimento} MT)";
} elseif (!$matchOC) {
$status = 'Com Excecao';
$motivo = "Divergência com OC: {$divergenciaOC} MT";
} elseif (!$matchRecebimento) {
$status = 'Com Excecao';
$motivo = "Divergência com Recebimento: {$divergenciaRecebimento} MT";
}
// Atualizar fatura
DB::transaction(function () use ($fatura, $status, $motivo) {
$fatura->update([
'status_3_way_match' => $status,
'motivo_excecao' => $motivo,
]);
});
Log::info('3-Way Match executado', [
'fatura_id' => $fatura->fatura_id,
'status' => $status,
'valor_fatura' => $valorFatura,
'valor_oc' => $valorOC,
'valor_recebido' => $valorTotalRecebido,
]);
return [
'status' => $status,
'motivo' => $motivo,
'valor_fatura' => $valorFatura,
'valor_oc' => $valorOC,
'valor_recebido' => $valorTotalRecebido,
'divergencia_oc' => $divergenciaOC,
'divergencia_recebimento' => $divergenciaRecebimento,
];
}
/**
* Processa todas as faturas pendentes de match
*/
public function processarPendentes(): int
{
$faturasPendentes = Fatura::where('status_3_way_match', 'Pendente')->get();
$processadas = 0;
foreach ($faturasPendentes as $fatura) {
$this->executarMatch($fatura);
$processadas++;
}
return $processadas;
}
}