First Commit

This commit is contained in:
marco
2026-09-01 10:46:29 -03:00
commit bf96b77e9c
10000 changed files with 3508600 additions and 0 deletions
+172
View File
@@ -0,0 +1,172 @@
{% extends "layouts/dashboard.twig" %}
{% block title %}{{ title }} - {{ platformName }}{% endblock %}
{% block content %}
<div class="container-fluid px-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="mt-4">{{ title }}</h1>
<div>
<a href="{{ url('/admin/fluxo-caixa') }}" class="btn btn-outline-secondary me-2">
<i class="bi bi-arrow-left me-1"></i> Voltar ao Fluxo
</a>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#newCategoryModal">
<i class="bi bi-plus-circle me-1"></i> Nova Categoria
</button>
</div>
</div>
{% if flash_messages.success %}
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ flash_messages.success }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endif %}
<div class="card shadow mb-4 border-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">Nome</th>
<th>Tipo Padrão</th>
<th>Cor</th>
<th>Ícone</th>
<th>Status</th>
<th class="text-center">Ações</th>
</tr>
</thead>
<tbody>
{% for cat in categories %}
<tr>
<td class="ps-4 fw-bold">{{ cat.name }}</td>
<td>
{% if cat.type == 'income' %}
<span class="text-success small"><i class="bi bi-plus-circle me-1"></i> Receita</span>
{% else %}
<span class="text-danger small"><i class="bi bi-dash-circle me-1"></i> Despesa</span>
{% endif %}
</td>
<td>
<div class="d-flex align-items-center">
<div style="width: 20px; height: 20px; border-radius: 50%; background-color: {{ cat.color }}; margin-right: 8px;"></div>
<small class="text-muted">{{ cat.color }}</small>
</div>
</td>
<td><i class="{{ cat.icon }} fs-5"></i></td>
<td>
{% if cat.is_active %}
<span class="badge bg-success">Ativa</span>
{% else %}
<span class="badge bg-secondary">Inativa</span>
{% endif %}
</td>
<td class="text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-primary border-0"
data-bs-toggle="modal" data-bs-target="#editCategoryModal{{ cat.id }}">
<i class="bi bi-pencil"></i>
</button>
<form action="{{ url('/admin/fluxo-caixa/categories/delete/' ~ cat.id) }}" method="POST">
<button type="submit" class="btn btn-sm btn-outline-{{ cat.is_active ? 'warning' : 'success' }} border-0">
<i class="bi bi-power"></i>
</button>
</form>
</div>
</td>
</tr>
<!-- Modal Editar Categoria -->
<div class="modal fade" id="editCategoryModal{{ cat.id }}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Editar Categoria: {{ cat.name }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ url('/admin/fluxo-caixa/categories/update/' ~ cat.id) }}" method="POST">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Nome da Categoria</label>
<input type="text" name="name" class="form-control" value="{{ cat.name }}" required>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Tipo Padrão</label>
<select name="type" class="form-select">
<option value="income" {{ cat.type == 'income' ? 'selected' : '' }}>Receita</option>
<option value="expense" {{ cat.type == 'expense' ? 'selected' : '' }}>Despesa</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Cor</label>
<input type="color" name="color" class="form-control form-control-color w-100" value="{{ cat.color }}">
</div>
</div>
<div class="mb-3">
<label class="form-label">Ícone (Bootstrap Icon)</label>
<input type="text" name="icon" class="form-control" value="{{ cat.icon }}" placeholder="bi bi-tag">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Salvar Alterações</button>
</div>
</form>
</div>
</div>
</div>
{% else %}
<tr>
<td colspan="6" class="text-center py-4 text-muted">Nenhuma categoria cadastrada.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Modal Nova Categoria -->
<div class="modal fade" id="newCategoryModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Nova Categoria</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ url('/admin/fluxo-caixa/categories/store') }}" method="POST">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Nome da Categoria</label>
<input type="text" name="name" class="form-control" required placeholder="Ex: Alimentação, Vendas...">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Tipo Padrão</label>
<select name="type" class="form-select">
<option value="income">Receita</option>
<option value="expense" selected>Despesa</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Cor</label>
<input type="color" name="color" class="form-control form-control-color w-100" value="#0d6efd">
</div>
</div>
<div class="mb-3">
<label class="form-label">Ícone (Bootstrap Icon)</label>
<input type="text" name="icon" class="form-control" value="bi bi-tag" placeholder="bi bi-tag">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Criar Categoria</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
+660
View File
@@ -0,0 +1,660 @@
{% extends "layouts/dashboard.twig" %}
{% block title %}{{ title }} - {{ platformName }}{% endblock %}
{% block head %}
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.card-metric { transition: transform 0.2s; cursor: pointer; }
.card-metric:hover { transform: translateY(-5px); }
.border-income { border-left: 5px solid #198754 !important; }
.border-expense { border-left: 5px solid #dc3545 !important; }
.border-balance { border-left: 5px solid #0dcaf0 !important; }
</style>
{% endblock %}
{% block content %}
<div class="container-fluid px-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="mt-4">{{ title }}</h1>
<div class="d-flex gap-2">
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#reconcileModal">
<i class="bi bi-bank me-1"></i> Conciliação
</button>
<a href="{{ url('/admin/fluxo-caixa/export') }}" class="btn btn-outline-success">
<i class="bi bi-file-earmark-excel me-1"></i> Exportar
</a>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#newTransactionModal">
<i class="bi bi-plus-circle me-1"></i> Nova Transação
</button>
<form action="{{ url('/admin/fluxo-caixa/analysis') }}" method="POST">
<button type="submit" class="btn btn-info text-white">
<i class="bi bi-cpu me-1"></i> Análise IA
</button>
</form>
<a href="{{ url('/admin/fluxo-caixa/categories') }}" class="btn btn-secondary">
<i class="bi bi-tags me-1"></i> Categorias
</a>
</div>
</div>
{% if flash_messages.success %}
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ flash_messages.success }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endif %}
<!-- Filtros de Período e Status -->
<div class="card mb-4 shadow-sm border-0">
<div class="card-body">
<form method="GET" class="row g-3 align-items-end">
<div class="col-md-3">
<label class="form-label small fw-bold">Período:</label>
<div class="input-group input-group-sm">
<input type="date" name="start_date" class="form-control" value="{{ startDate }}">
<span class="input-group-text">até</span>
<input type="date" name="end_date" class="form-control" value="{{ endDate }}">
</div>
</div>
<div class="col-md-2">
<label class="form-label small fw-bold">Status:</label>
<select name="status" class="form-select form-select-sm">
<option value="">Todos</option>
<option value="paid" {{ filters.status == 'paid' ? 'selected' : '' }}>Pago</option>
<option value="pending" {{ filters.status == 'pending' ? 'selected' : '' }}>Pendente</option>
</select>
</div>
<div class="col-md-2">
<label class="form-label small fw-bold">Tipo:</label>
<select name="type" class="form-select form-select-sm">
<option value="">Todos</option>
<option value="income" {{ filters.type == 'income' ? 'selected' : '' }}>Entrada</option>
<option value="expense" {{ filters.type == 'expense' ? 'selected' : '' }}>Saída</option>
</select>
</div>
<div class="col-md-2">
<label class="form-label small fw-bold">Entidade:</label>
<select name="entity" class="form-select form-select-sm">
<option value="">Todos</option>
<option value="business" {{ filters.entity == 'business' ? 'selected' : '' }}>Empresa</option>
<option value="personal" {{ filters.entity == 'personal' ? 'selected' : '' }}>Pessoal</option>
</select>
</div>
<div class="col-md-3">
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary btn-sm flex-grow-1">
<i class="bi bi-filter me-1"></i> Filtrar
</button>
<a href="{{ url('/admin/fluxo-caixa') }}" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-x-circle"></i>
</a>
</div>
</div>
</form>
</div>
</div>
<!-- Cards de Métricas Principais -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6">
<div class="card card-metric shadow-sm border-0 border-income h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Receitas (Operacional)</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">R$ {{ summary.operational_income|number_format(2, ',', '.') }}</div>
<small class="text-muted">Total: R$ {{ summary.total_income|number_format(2, ',', '.') }}</small>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="card card-metric shadow-sm border-0 border-expense h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Despesas (Operacional)</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">R$ {{ summary.operational_expense|number_format(2, ',', '.') }}</div>
<small class="text-muted">Total: R$ {{ summary.total_expense|number_format(2, ',', '.') }}</small>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="card card-metric shadow-sm border-0 border-info h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Saldo Operacional</div>
<div class="h5 mb-0 font-weight-bold {{ summary.operational_balance >= 0 ? 'text-info' : 'text-danger' }}">
R$ {{ summary.operational_balance|number_format(2, ',', '.') }}
</div>
<small class="text-muted">Líquido: R$ {{ summary.net_balance|number_format(2, ',', '.') }}</small>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="card card-metric shadow-sm border-0 border-warning h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Contas Pendentes</div>
<div class="small">A Receber: <span class="text-success fw-bold">R$ {{ summary.pending_income|number_format(2, ',', '.') }}</span></div>
<div class="small">A Pagar: <span class="text-danger fw-bold">R$ {{ summary.pending_expense|number_format(2, ',', '.') }}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<!-- Gráfico Mensal -->
<div class="col-lg-6">
<div class="card shadow-sm border-0 h-100">
<div class="card-header bg-white border-0 py-3">
<h6 class="m-0 font-weight-bold text-primary">Fluxo Mensal (Histórico)</h6>
</div>
<div class="card-body">
<canvas id="monthlyChart" style="min-height: 300px;"></canvas>
</div>
</div>
</div>
<!-- Projeções -->
<div class="col-lg-6">
<div class="card shadow-sm border-0 h-100">
<div class="card-header bg-white border-0 py-3">
<h6 class="m-0 font-weight-bold text-primary">Projeção de Saldo (12 Meses)</h6>
</div>
<div class="card-body">
<canvas id="projectionChart" style="min-height: 300px;"></canvas>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<!-- IA Insights -->
<div class="col-lg-12">
<div class="card shadow-sm border-0 h-100 bg-light">
<div class="card-header bg-white border-0 py-3 d-flex justify-content-between align-items-center">
<h6 class="m-0 font-weight-bold text-info"><i class="bi bi-robot me-2"></i>Insights da Inteligência Artificial</h6>
{% if latestAnalysis %}
<small class="text-muted">Última análise: {{ latestAnalysis.created_at|date('d/m/Y H:i') }}</small>
{% endif %}
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3">
{% if latestAnalysis %}
<div class="mb-3">
<small class="text-muted d-block mb-1">Previsão de Saldo Próximo Mês:</small>
<span class="h4 fw-bold text-primary">R$ {{ latestAnalysis.summary_data.predicted_balance|number_format(2, ',', '.') }}</span>
</div>
<div class="mb-3">
<small class="text-muted d-block mb-1">Nível de Risco Financeiro:</small>
{% set risk = latestAnalysis.summary_data.risk_level %}
<span class="badge fs-6 bg-{{ risk == 'High' ? 'danger' : (risk == 'Medium' ? 'warning' : 'success') }}">
{{ risk == 'High' ? 'Alto Risco' : (risk == 'Medium' ? 'Risco Médio' : 'Baixo Risco') }}
</span>
</div>
{% else %}
<div class="text-center py-4">
<i class="bi bi-cpu fs-1 text-muted opacity-25"></i>
<p class="text-muted mt-2 small">Sem análise recente.</p>
</div>
{% endif %}
</div>
<div class="col-md-9">
{% if latestAnalysis %}
<div class="p-3 bg-white rounded border">
<h6 class="fw-bold mb-2">Recomendações Estratégicas:</h6>
<p class="text-dark mb-0" style="white-space: pre-line;">{{ latestAnalysis.recommendations }}</p>
</div>
{% else %}
<div class="alert alert-info mb-0">
<i class="bi bi-info-circle me-2"></i> Clique no botão <strong>Análise IA</strong> no topo para que nosso sistema examine seu fluxo de caixa e forneça recomendações personalizadas baseadas em melhores práticas de gestão financeira.
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Últimas Transações -->
<div class="card shadow-sm border-0 mb-4">
<div class="card-header bg-white border-0 py-3">
<h6 class="m-0 font-weight-bold text-primary">Últimas Transações</h6>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">Data</th>
<th>Descrição</th>
<th>Categoria</th>
<th>Tipo</th>
<th>Valor</th>
<th>Status</th>
<th class="text-end pe-4">Ações</th>
</tr>
</thead>
<tbody>
{% for trans in latestTransactions %}
<tr>
<td class="ps-4 small">
<span class="text-muted d-block">{{ trans.transaction_date|date('d/m/Y') }}</span>
{% if trans.due_date %}
<small class="text-info">Venc: {{ trans.due_date|date('d/m/Y') }}</small>
{% endif %}
</td>
<td>
{{ trans.description }}
{% if trans.is_personal %}
<span class="badge bg-secondary ms-1" title="Despesa/Receita Pessoal">Pessoal</span>
{% endif %}
</td>
<td>
<span class="badge" style="background-color: {{ trans.category.color }};">
<i class="{{ trans.category.icon }} me-1"></i>{{ trans.category.name }}
</span>
</td>
<td>
<span class="text-{{ trans.type == 'income' ? 'success' : 'danger' }} small fw-bold">
{{ trans.type == 'income' ? 'Entrada' : 'Saída' }}
</span>
</td>
<td class="fw-bold {{ trans.type == 'income' ? 'text-success' : 'text-danger' }}">
{{ trans.type == 'income' ? '+' : '-' }} R$ {{ trans.amount|abs|number_format(2, ',', '.') }}
</td>
<td>
<span class="badge bg-{{ trans.status == 'paid' ? 'success' : 'warning' }}">
{{ trans.status == 'paid' ? 'Pago' : 'Pendente' }}
</span>
</td>
<td class="text-end pe-4">
<div class="btn-group btn-group-sm">
{% if trans.status == 'pending' %}
<form action="{{ url('/admin/fluxo-caixa/transaction/pay/' ~ trans.id) }}" method="POST" class="d-inline">
<button type="submit" class="btn btn-outline-success" title="Marcar como Pago">
<i class="bi bi-check2-circle"></i>
</button>
</form>
{% endif %}
<button type="button" class="btn btn-outline-primary"
data-bs-toggle="modal"
data-bs-target="#editTransactionModal{{ trans.id }}"
title="Editar">
<i class="bi bi-pencil"></i>
</button>
<button type="button" class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#deleteTransactionModal{{ trans.id }}"
title="Excluir">
<i class="bi bi-trash"></i>
</button>
</div>
<!-- Modal Editar Transação -->
<div class="modal fade" id="editTransactionModal{{ trans.id }}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog text-start">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Editar Transação</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ url('/admin/fluxo-caixa/transaction/update/' ~ trans.id) }}" method="POST">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Descrição</label>
<input type="text" name="description" class="form-control" value="{{ trans.description }}" required>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Valor (R$)</label>
<input type="number" step="0.01" name="amount" class="form-control" value="{{ trans.amount }}" required>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Data Lançamento</label>
<input type="date" name="transaction_date" class="form-control" value="{{ trans.transaction_date|date('Y-m-d') }}" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Data Vencimento</label>
<input type="date" name="due_date" class="form-control" value="{{ trans.due_date ? trans.due_date|date('Y-m-d') : '' }}">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Data Pagamento</label>
<input type="date" name="payment_date" class="form-control" value="{{ trans.payment_date ? trans.payment_date|date('Y-m-d') : '' }}">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Tipo</label>
<select name="type" class="form-select">
<option value="income" {{ trans.type == 'income' ? 'selected' : '' }}>Receita</option>
<option value="expense" {{ trans.type == 'expense' ? 'selected' : '' }}>Despesa</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Categoria</label>
<select name="category_id" class="form-select" required>
{% for cat in categories_all %}
<option value="{{ cat.id }}" {{ cat.id == trans.category_id ? 'selected' : '' }}>{{ cat.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-6">
<label class="form-label">Status</label>
<div class="d-flex gap-3">
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="paid" {{ trans.status == 'paid' ? 'checked' : '' }}>
<label class="form-check-label">Pago</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="pending" {{ trans.status == 'pending' ? 'checked' : '' }}>
<label class="form-check-label">Pendente</label>
</div>
</div>
</div>
<div class="col-md-6 pt-4">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="is_personal" value="1" id="editIsPersonal{{ trans.id }}" {{ trans.is_personal ? 'checked' : '' }}>
<label class="form-check-label" for="editIsPersonal{{ trans.id }}">Gasto Pessoal?</label>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Observações</label>
<textarea name="notes" class="form-control" rows="2">{{ trans.notes }}</textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Salvar Alterações</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal Excluir Transação -->
<div class="modal fade" id="deleteTransactionModal{{ trans.id }}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog text-start">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Excluir Transação</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Tem certeza que deseja excluir a transação <strong>"{{ trans.description }}"</strong>?</p>
<p class="text-danger small"><i class="bi bi-exclamation-triangle me-1"></i> Esta ação não pode ser desfeita.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<form action="{{ url('/admin/fluxo-caixa/transaction/delete/' ~ trans.id) }}" method="POST">
<button type="submit" class="btn btn-danger">Excluir</button>
</form>
</div>
</div>
</div>
</div>
</td>
</tr>
{% else %}
<tr>
<td colspan="5" class="text-center py-4 text-muted">Nenhuma transação encontrada.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Modal Nova Transação -->
<div class="modal fade" id="newTransactionModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Nova Transação</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ url('/admin/fluxo-caixa/transaction') }}" method="POST">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Descrição</label>
<input type="text" name="description" class="form-control" required placeholder="Ex: Pagamento Fornecedor X">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Valor (R$)</label>
<input type="number" step="0.01" name="amount" class="form-control" required>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Data Lançamento</label>
<input type="date" name="transaction_date" class="form-control" value="{{ "now"|date("Y-m-d") }}" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Data Vencimento</label>
<input type="date" name="due_date" class="form-control">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Data Pagamento</label>
<input type="date" name="payment_date" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Tipo</label>
<select name="type" class="form-select" id="trans_type">
<option value="income">Receita</option>
<option value="expense" selected>Despesa</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Categoria</label>
<select name="category_id" class="form-select" required>
{% for cat in categories_all %}
<option value="{{ cat.id }}" data-type="{{ cat.type }}">{{ cat.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-6">
<label class="form-label">Status</label>
<div class="d-flex gap-3">
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="paid" checked>
<label class="form-check-label">Pago</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="status" value="pending">
<label class="form-check-label">Pendente</label>
</div>
</div>
</div>
<div class="col-md-6 pt-4">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="is_personal" value="1" id="isPersonalSwitch">
<label class="form-check-label" for="isPersonalSwitch">Gasto Pessoal?</label>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Observações</label>
<textarea name="notes" class="form-control" rows="2"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Salvar Transação</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal Conciliação Bancária -->
<div class="modal fade" id="reconcileModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Conciliação Bancária</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ url('/admin/fluxo-caixa/reconcile') }}" method="POST">
<div class="modal-body">
<p class="small text-muted mb-3">
Insira o saldo atual que aparece no extrato do seu banco para comparar com o saldo registrado no sistema.
</p>
<div class="mb-3">
<label class="form-label">Saldo Atual no Banco (R$)</label>
<input type="number" step="0.01" name="bank_balance" class="form-control" required placeholder="0,00">
</div>
<div class="alert alert-info py-2 small mb-0">
<i class="bi bi-info-circle me-1"></i> O sistema utilizará o <strong>Saldo Líquido Total</strong> (Empresa + Pessoal) para esta conferência.
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Conciliar Agora</button>
</div>
</form>
</div>
</div>
</div>
{% block scripts %}
<script>
const monthlyData = {{ monthlyBreakdown|raw }};
const projectionsData = {{ projections|raw }};
// Configuração comum para tooltips de moeda
const currencyTooltip = {
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) label += ': ';
if (context.parsed.y !== null) {
label += 'R$ ' + context.parsed.y.toLocaleString('pt-BR', {minimumFractionDigits: 2});
}
return label;
}
}
};
// Gráfico Histórico
const ctxMonthly = document.getElementById('monthlyChart').getContext('2d');
new Chart(ctxMonthly, {
type: 'bar',
data: {
labels: monthlyData.map(d => d.month),
datasets: [
{
label: 'Receitas',
data: monthlyData.map(d => d.income),
backgroundColor: 'rgba(25, 135, 84, 0.7)',
borderColor: 'rgb(25, 135, 84)',
borderWidth: 1
},
{
label: 'Despesas',
data: monthlyData.map(d => d.expense),
backgroundColor: 'rgba(220, 53, 69, 0.7)',
borderColor: 'rgb(220, 53, 69)',
borderWidth: 1
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return 'R$ ' + value.toLocaleString('pt-BR');
}
}
}
},
plugins: {
tooltip: currencyTooltip
}
}
});
// Gráfico de Projeções
const ctxProjection = document.getElementById('projectionChart').getContext('2d');
new Chart(ctxProjection, {
type: 'line',
data: {
labels: projectionsData.map(d => d.month),
datasets: [
{
label: 'Cenário Otimista',
data: projectionsData.map(d => d.optimistic.balance),
borderColor: 'rgba(25, 135, 84, 0.8)',
backgroundColor: 'rgba(25, 135, 84, 0.1)',
borderDash: [5, 5],
fill: false,
tension: 0.4
},
{
label: 'Cenário Realista',
data: projectionsData.map(d => d.realistic.balance),
borderColor: 'rgba(13, 202, 240, 1)',
backgroundColor: 'rgba(13, 202, 240, 0.1)',
fill: true,
tension: 0.4,
borderWidth: 3
},
{
label: 'Cenário Pessimista',
data: projectionsData.map(d => d.pessimistic.balance),
borderColor: 'rgba(220, 53, 69, 0.8)',
backgroundColor: 'rgba(220, 53, 69, 0.1)',
borderDash: [5, 5],
fill: false,
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
ticks: {
callback: function(value) {
return 'R$ ' + value.toLocaleString('pt-BR');
}
}
}
},
plugins: {
tooltip: currencyTooltip
}
}
});
</script>
{% endblock %}
{% endblock %}
@@ -0,0 +1,77 @@
{% extends "layouts/dashboard.twig" %}
{% block title %}{{ title }} - {{ platformName }}{% endblock %}
{% block content %}
<div class="container-fluid px-4">
<h1 class="mt-4">{{ title }}</h1>
<div class="row mt-4">
<div class="col-lg-6">
<div class="card shadow-sm border-0 mb-4">
<div class="card-header bg-white border-0 py-3">
<h6 class="m-0 font-weight-bold text-primary">Resumo da Conciliação</h6>
</div>
<div class="card-body">
<div class="d-flex justify-content-between mb-3">
<span>Saldo no Banco:</span>
<span class="fw-bold">R$ {{ bankBalance|number_format(2, ',', '.') }}</span>
</div>
<div class="d-flex justify-content-between mb-3">
<span>Saldo no Sistema:</span>
<span class="fw-bold">R$ {{ systemBalance|number_format(2, ',', '.') }}</span>
</div>
<hr>
<div class="d-flex justify-content-between">
<span class="h5">Diferença:</span>
<span class="h5 fw-bold {{ difference == 0 ? 'text-success' : 'text-danger' }}">
R$ {{ difference|number_format(2, ',', '.') }}
</span>
</div>
</div>
</div>
{% if difference != 0 %}
<div class="alert alert-warning">
<i class="bi bi-exclamation-triangle-fill me-2"></i>
<strong>Atenção!</strong> Existe uma diferença de R$ {{ difference|abs|number_format(2, ',', '.') }} entre o banco e o sistema.
<br><br>
<strong>Sugestões de gestão para resolver:</strong>
<ul class="mt-2">
<li>Verifique se todas as tarifas bancárias foram lançadas.</li>
<li>Confira se algum cheque ou transferência ainda não compensou.</li>
<li>Verifique se houve algum erro de digitação nos valores.</li>
<li>Certifique-se de que não houve mistura de gastos pessoais (que não foram lançados).</li>
</ul>
</div>
{% else %}
<div class="alert alert-success">
<i class="bi bi-check-circle-fill me-2"></i>
<strong>Tudo certo!</strong> O saldo do banco coincide perfeitamente com o saldo do sistema. Sua gestão está excelente!
</div>
{% endif %}
<a href="{{ url('/admin/fluxo-caixa') }}" class="btn btn-primary mt-3">
<i class="bi bi-arrow-left me-1"></i> Voltar ao Dashboard
</a>
</div>
<div class="col-lg-6">
<div class="card shadow-sm border-0 bg-light">
<div class="card-body">
<h6 class="fw-bold mb-3">O que é Conciliação Bancária?</h6>
<p class="small text-muted">
A conciliação bancária consiste em conferir se o saldo do controle interno da empresa bate com o saldo do extrato bancário.
</p>
<p class="small text-muted">
Este processo deve ser feito diariamente ou, no máximo, semanalmente para evitar que erros se acumulem e distorçam a realidade financeira da sua empresa.
</p>
<div class="text-center mt-4">
<i class="bi bi-bank fs-1 text-primary opacity-25"></i>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}