commit melhorias sgf
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Sgc;
|
||||
|
||||
use App\Models\Sgc\Fatura;
|
||||
use App\Models\Sgc\Fornecedor;
|
||||
use App\Models\Sgc\OrdemCompra;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class IntegrationService
|
||||
{
|
||||
private ThreeWayMatchService $matchService;
|
||||
private BudgetCommitmentService $budgetService;
|
||||
|
||||
public function __construct(
|
||||
ThreeWayMatchService $matchService,
|
||||
BudgetCommitmentService $budgetService
|
||||
) {
|
||||
$this->matchService = $matchService;
|
||||
$this->budgetService = $budgetService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recebe fatura do SGC e processa no SGF
|
||||
*/
|
||||
public function receberFatura(array $payload, string $idempotencyKey): array
|
||||
{
|
||||
// Verificar idempotência
|
||||
$logExistente = DB::table('sgc_integration_log')
|
||||
->where('idempotency_key', $idempotencyKey)
|
||||
->first();
|
||||
|
||||
if ($logExistente) {
|
||||
return [
|
||||
'status' => 'DUPLICATE',
|
||||
'original_receipt_id' => $logExistente->id,
|
||||
'message' => 'Idempotency key já processada',
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
$resultado = DB::transaction(function () use ($payload) {
|
||||
// Buscar ou criar fornecedor
|
||||
$fornecedor = $this->sincronizarFornecedor($payload['supplier']);
|
||||
|
||||
// Buscar OC
|
||||
$oc = OrdemCompra::where('oc_id', $payload['oc_reference'])->first();
|
||||
if (!$oc) {
|
||||
throw new \Exception('OC não encontrada: ' . $payload['oc_reference']);
|
||||
}
|
||||
|
||||
// Verificar se fornecedor bate
|
||||
if ($oc->fornecedor_id !== $fornecedor->id) {
|
||||
throw new \Exception('Fornecedor não corresponde à OC');
|
||||
}
|
||||
|
||||
// Criar fatura
|
||||
$fatura = Fatura::create([
|
||||
'fatura_id' => $payload['sgf_invoice_id'],
|
||||
'ordem_compra_id' => $oc->id,
|
||||
'fornecedor_id' => $fornecedor->id,
|
||||
'data_fatura' => $payload['dates']['invoice_date'],
|
||||
'data_vencimento' => $payload['dates']['due_date'],
|
||||
'valor_fatura' => $payload['amounts']['subtotal'],
|
||||
'iva_valor' => $payload['amounts']['iva_amount'],
|
||||
'moeda' => $payload['amounts']['currency'],
|
||||
'taxa_cambio' => $payload['amounts']['exchange_rate'],
|
||||
'status_3_way_match' => 'Pendente',
|
||||
'status_pagamento' => 'Aguardando',
|
||||
'sgf_doc_number' => $payload['sgf_doc_number'],
|
||||
]);
|
||||
|
||||
// Executar 3-Way Match
|
||||
$matchResult = $this->matchService->executarMatch($fatura);
|
||||
|
||||
return [
|
||||
'status' => 'ACCEPTED',
|
||||
'fatura_id' => $fatura->id,
|
||||
'sgf_doc_number' => $fatura->sgf_doc_number,
|
||||
'match_result' => $matchResult,
|
||||
];
|
||||
});
|
||||
|
||||
// Log de sucesso
|
||||
DB::table('sgc_integration_log')->insert([
|
||||
'idempotency_key' => $idempotencyKey,
|
||||
'endpoint' => '/api/v1/integration/sgc/invoices',
|
||||
'event_type' => 'INVOICE_CREATED',
|
||||
'payload' => json_encode($payload),
|
||||
'status' => 'ACCEPTED',
|
||||
'response' => json_encode($resultado),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $resultado;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Log de erro
|
||||
DB::table('sgc_integration_log')->insert([
|
||||
'idempotency_key' => $idempotencyKey,
|
||||
'endpoint' => '/api/v1/integration/sgc/invoices',
|
||||
'event_type' => 'INVOICE_CREATED',
|
||||
'payload' => json_encode($payload),
|
||||
'status' => 'REJECTED',
|
||||
'error_code' => 'PROCESSING_ERROR',
|
||||
'error_message' => $e->getMessage(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
Log::error('Erro ao processar fatura', [
|
||||
'idempotency_key' => $idempotencyKey,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'status' => 'REJECTED',
|
||||
'error_code' => 'PROCESSING_ERROR',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recebe confirmação de pagamento do SGC
|
||||
*/
|
||||
public function receberPagamento(array $payload, string $idempotencyKey): array
|
||||
{
|
||||
// Verificar idempotência
|
||||
$logExistente = DB::table('sgc_integration_log')
|
||||
->where('idempotency_key', $idempotencyKey)
|
||||
->first();
|
||||
|
||||
if ($logExistente) {
|
||||
return [
|
||||
'status' => 'DUPLICATE',
|
||||
'original_receipt_id' => $logExistente->id,
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
$resultado = DB::transaction(function () use ($payload) {
|
||||
// Buscar fatura
|
||||
$fatura = Fatura::where('sgf_doc_number', $payload['sgf_doc_number'])->first();
|
||||
if (!$fatura) {
|
||||
throw new \Exception('Fatura não encontrada: ' . $payload['sgf_doc_number']);
|
||||
}
|
||||
|
||||
// Atualizar fatura com pagamento
|
||||
$fatura->update([
|
||||
'data_pagamento' => $payload['payment_date'],
|
||||
'valor_pago' => $payload['amount_paid'],
|
||||
'status_pagamento' => 'Pago',
|
||||
'numero_comprovativo' => $payload['bank_reference'],
|
||||
]);
|
||||
|
||||
// Atualizar OC se totalmente paga
|
||||
$oc = $fatura->ordemCompra;
|
||||
$totalPago = $oc->faturas()->where('status_pagamento', 'Pago')->sum('valor_pago');
|
||||
|
||||
if ($totalPago >= $oc->valor_comprometido) {
|
||||
$oc->update(['status' => 'Totalmente Paga']);
|
||||
}
|
||||
|
||||
return [
|
||||
'status' => 'ACCEPTED',
|
||||
'fatura_id' => $fatura->id,
|
||||
'payment_id' => $payload['payment_id'],
|
||||
];
|
||||
});
|
||||
|
||||
// Log de sucesso
|
||||
DB::table('sgc_integration_log')->insert([
|
||||
'idempotency_key' => $idempotencyKey,
|
||||
'endpoint' => '/api/v1/integration/sgc/payments',
|
||||
'event_type' => 'PAYMENT_EXECUTED',
|
||||
'payload' => json_encode($payload),
|
||||
'status' => 'ACCEPTED',
|
||||
'response' => json_encode($resultado),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $resultado;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::table('sgc_integration_log')->insert([
|
||||
'idempotency_key' => $idempotencyKey,
|
||||
'endpoint' => '/api/v1/integration/sgc/payments',
|
||||
'event_type' => 'PAYMENT_EXECUTED',
|
||||
'payload' => json_encode($payload),
|
||||
'status' => 'REJECTED',
|
||||
'error_code' => 'PROCESSING_ERROR',
|
||||
'error_message' => $e->getMessage(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'status' => 'REJECTED',
|
||||
'error_code' => 'PROCESSING_ERROR',
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sincroniza fornecedor do SGC para o SGF
|
||||
*/
|
||||
private function sincronizarFornecedor(array $supplierData): Fornecedor
|
||||
{
|
||||
return Fornecedor::updateOrCreate(
|
||||
['sgf_fornecedor_id' => $supplierData['sgf_supplier_id']],
|
||||
[
|
||||
'nuit' => $supplierData['nuit'],
|
||||
'nome_fornecedor' => $supplierData['name'],
|
||||
'categoria_fornecedor' => $supplierData['category'] ?? 'Geral',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user