Gestão Completa de Finanças
Gestão completa de doações, campanhas e finanças
"Honra ao Senhor com os teus bens e com as primícias de toda a tua renda"
Provérbios 3:9
O Sistema Financeiro do CBAV oferece controle total sobre doações, campanhas, dízimos e todas as transações financeiras da igreja. Integrado com múltiplos gateways de pagamento, proporciona transparência e eficiência na gestão financeira.
Stripe, Mercado Pago e PIX
Análises e estatísticas detalhadas
Proteção e validação de transações
Plataforma completa para recebimento de doações com múltiplos gateways de pagamento.
Criação e gestão de campanhas específicas com metas e relatórios.
Sistema completo de controle e validação de todas as transações financeiras.
Relatórios detalhados e análises avançadas da situação financeira.
Sistema robusto de segurança e validação de todas as transações.
Sistema de notificações automáticas para doadores e administradores.
Gateway internacional com suporte a cartões de crédito e débito.
Gateway brasileiro com múltiplas formas de pagamento.
Transferência instantânea via PIX do Banco Central.
CREATE TABLE transacoes (
id BIGINT PRIMARY KEY,
membro_id BIGINT NULL,
campanha_id BIGINT NULL,
tipo ENUM('dizimo', 'oferta', 'doacao', 'saida', 'entrada'),
valor DECIMAL(10,2) NOT NULL,
descricao TEXT,
data DATE NOT NULL,
status ENUM('pendente', 'confirmado', 'cancelado'),
comprovante VARCHAR(255) NULL,
dados_extras JSON NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE campanhas (
id BIGINT PRIMARY KEY,
nome VARCHAR(255) NOT NULL,
descricao TEXT,
valor_meta DECIMAL(10,2),
valor_atual DECIMAL(10,2) DEFAULT 0,
data_inicio DATE,
data_fim DATE,
ativo BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE pagamentos (
id BIGINT PRIMARY KEY,
transacao_id BIGINT,
gateway ENUM('stripe', 'mercadopago', 'pix'),
gateway_id VARCHAR(255) NULL,
gateway_status VARCHAR(255) NULL,
valor DECIMAL(10,2),
moeda VARCHAR(10) DEFAULT 'BRL',
dados_gateway JSON NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE configuracoes (
id BIGINT PRIMARY KEY,
chave VARCHAR(255) UNIQUE,
valor TEXT,
descricao TEXT,
tipo ENUM('string', 'number', 'boolean', 'json'),
created_at TIMESTAMP,
updated_at TIMESTAMP
);
// Rotas Públicas de Doação
Route::prefix('doacao')->name('doacao.')->middleware('check.payment.gateways')->group(function () {
Route::get('/', [PublicDonationController::class, 'index'])->name('index');
Route::post('/processar', [PublicDonationController::class, 'process'])->name('process');
Route::get('/confirmacao/{transacao}', [PublicDonationController::class, 'confirmation'])->name('confirmation');
});
// Rotas de Pagamento
Route::prefix('payment')->name('payment.')->group(function () {
Route::post('/stripe', [PagamentoController::class, 'processStripe'])->name('stripe');
Route::post('/mercadopago', [PagamentoController::class, 'processMercadoPago'])->name('mercadopago');
Route::post('/pix', [PagamentoController::class, 'generatePix'])->name('pix');
Route::post('/webhook/stripe', [PagamentoController::class, 'webhookStripe'])->name('webhook.stripe');
Route::post('/webhook/mercadopago', [PagamentoController::class, 'webhookMercadoPago'])->name('webhook.mercadopago');
});
// Rotas Admin
Route::prefix('admin/finance')->name('admin.finance.')->middleware(['auth', 'admin'])->group(function () {
Route::get('/', [FinanceController::class, 'index'])->name('index');
Route::resource('transactions', TransacaoController::class);
Route::resource('campaigns', CampanhaController::class);
Route::get('reports', [RelatorioController::class, 'index'])->name('reports');
});
class Transacao extends Model
{
protected $fillable = [
'membro_id', 'campanha_id', 'tipo', 'valor',
'descricao', 'data', 'status', 'comprovante', 'dados_extras'
];
protected $casts = [
'valor' => 'decimal:2',
'data' => 'date',
'dados_extras' => 'array',
];
public function membro()
{
return $this->belongsTo(Membro::class);
}
public function campanha()
{
return $this->belongsTo(Campanha::class);
}
public function pagamentos()
{
return $this->hasMany(Pagamento::class);
}
}
class Campanha extends Model
{
protected $fillable = [
'nome', 'descricao', 'valor_meta', 'valor_atual',
'data_inicio', 'data_fim', 'ativo'
];
protected $casts = [
'valor_meta' => 'decimal:2',
'valor_atual' => 'decimal:2',
'data_inicio' => 'date',
'data_fim' => 'date',
'ativo' => 'boolean',
];
public function transacoes()
{
return $this->hasMany(Transacao::class);
}
public function getProgressoAttribute()
{
if ($this->valor_meta > 0) {
return ($this->valor_atual / $this->valor_meta) * 100;
}
return 0;
}
}
class Pagamento extends Model
{
protected $fillable = [
'transacao_id', 'gateway', 'gateway_id',
'gateway_status', 'valor', 'moeda', 'dados_gateway'
];
protected $casts = [
'valor' => 'decimal:2',
'dados_gateway' => 'array',
];
public function transacao()
{
return $this->belongsTo(Transacao::class);
}
}
// PublicDonationController.php
public function process(Request $request)
{
$request->validate([
'valor' => 'required|numeric|min:1',
'campanha_id' => 'nullable|exists:campanhas,id',
'gateway' => 'required|in:stripe,mercadopago,pix',
'dados_pagamento' => 'required|array'
]);
$transacao = Transacao::create([
'tipo' => 'doacao',
'valor' => $request->valor,
'campanha_id' => $request->campanha_id,
'data' => now(),
'status' => 'pendente',
'dados_extras' => $request->dados_pagamento
]);
// Processar pagamento baseado no gateway
switch ($request->gateway) {
case 'stripe':
return $this->processStripe($transacao, $request->dados_pagamento);
case 'mercadopago':
return $this->processMercadoPago($transacao, $request->dados_pagamento);
case 'pix':
return $this->processPix($transacao, $request->dados_pagamento);
}
}
// CampanhaController.php
public function store(Request $request)
{
$request->validate([
'nome' => 'required|string|max:255',
'descricao' => 'nullable|string',
'valor_meta' => 'required|numeric|min:0',
'data_inicio' => 'required|date',
'data_fim' => 'nullable|date|after:data_inicio'
]);
$campanha = Campanha::create([
'nome' => $request->nome,
'descricao' => $request->descricao,
'valor_meta' => $request->valor_meta,
'valor_atual' => 0,
'data_inicio' => $request->data_inicio,
'data_fim' => $request->data_fim,
'ativo' => true
]);
return redirect()->route('admin.finance.campaigns.index')
->with('success', 'Campanha criada com sucesso!');
}
// RelatorioController.php
public function relatorioFinanceiro(Request $request)
{
$dataInicio = $request->get('data_inicio', now()->startOfMonth());
$dataFim = $request->get('data_fim', now()->endOfMonth());
$transacoes = Transacao::whereBetween('data', [$dataInicio, $dataFim])
->where('status', 'confirmado')
->with(['membro', 'campanha'])
->get();
$estatisticas = [
'total_doacoes' => $transacoes->where('tipo', 'doacao')->sum('valor'),
'total_dizimos' => $transacoes->where('tipo', 'dizimo')->sum('valor'),
'total_ofertas' => $transacoes->where('tipo', 'oferta')->sum('valor'),
'quantidade_transacoes' => $transacoes->count(),
'media_por_transacao' => $transacoes->avg('valor'),
'doacoes_por_gateway' => $transacoes->groupBy('gateway')
];
return view('admin.finance.reports.financial', compact('transacoes', 'estatisticas'));
}
Análise detalhada de todas as doações recebidas.
Acompanhamento do progresso das campanhas ativas.
Análise de performance dos gateways de pagamento.
Análise do crescimento financeiro da igreja.
// PagamentoController.php
public function webhookStripe(Request $request)
{
$payload = $request->getContent();
$sig_header = $request->header('Stripe-Signature');
$endpoint_secret = config('services.stripe.webhook_secret');
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
return response('Invalid payload', 400);
} catch(\Stripe\Exception\SignatureVerificationException $e) {
return response('Invalid signature', 400);
}
// Processar evento
switch ($event->type) {
case 'payment_intent.succeeded':
$this->handlePaymentSuccess($event->data->object);
break;
case 'payment_intent.payment_failed':
$this->handlePaymentFailure($event->data->object);
break;
}
return response('Webhook handled', 200);
}