BREAKING CHANGES: - Sistema de permissões movido do nível de template para nível de dados - Menus sempre visíveis, controle transparente no backend - Templates nunca quebram, sempre renderizam com dados filtrados Features: - ✅ Arquitetura MVC completa implementada - ✅ Controllers com filtragem hierárquica de dados - ✅ Template helpers simplificados (user_can sempre True) - ✅ Controle de acesso baseado na hierarquia organizacional - ✅ Regra especial para tesoureiros (acesso completo) - ✅ Tratamento robusto de erros em todos os controllers Controllers implementados: - militante_controller.py - Filtragem por célula/setor/CR/CC - cota_controller.py - Controle baseado em permissões - material_controller.py - Acesso flexível por nível - pagamento_controller.py - Filtragem organizacional - auth_controller.py - Autenticação com OTP - home_controller.py - Dashboard com estatísticas - usuario_controller.py - Gestão de usuários Templates corrigidos: - listar_cotas.html - URLs corrigidas (nova_cota → cota.nova) - listar_tipos_materiais.html - Variáveis ajustadas (tipos → tipos_materiais) - base.html - Menus sempre visíveis - Diversos templates com correções de URLs e referências Services implementados: - auth_service.py - Lógica de autenticação - dashboard_service.py - Estatísticas do dashboard - cache_service.py - Integração com Redis - celula_service.py - Operações de células Models implementados: - militante_model.py - Operações de militantes - pagamento_model.py - Operações de pagamentos Documentação: - docs/permission_fixes_summary.md - Resumo completo das correções - docs/architecture_summary.md - Arquitetura MVC - docs/mvc_refactoring.md - Detalhes da refatoração - docs/permission_strategy.md - Estratégia de permissões - docs/redis_cache_setup.md - Setup do cache Redis - README.md atualizado com nova arquitetura Testes: - test_menu_navigation.py - Testes unitários de navegação - test_integration_menu.py - Testes de integração com Selenium Status dos testes: ✅ Funcionais: /, /dashboard, /pagamentos, /materiais ❌ Com problemas: /militantes, /cotas, /tipos-materiais, /admin/dashboard Hierarquia de permissões implementada: Admin → Acesso total CC → Acesso total CR → Dados do CR Setor → Dados do setor Célula → Dados da célula Próximos passos identificados: - Corrigir referências a Militante indefinido nos templates - Resolver problemas de campos inexistentes - Corrigir roteamento admin
204 lines
10 KiB
HTML
204 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Pagamentos{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid mt-3">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h2><i class="fas fa-money-bill-wave"></i> Pagamentos</h2>
|
|
<div>
|
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalNovoPagamento">
|
|
<i class="fas fa-plus"></i> Novo Pagamento
|
|
</button>
|
|
<button type="button" class="btn btn-outline-primary" id="btnExportar">
|
|
<i class="fas fa-file-export"></i> Exportar
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-hover" id="tabelaPagamentos">
|
|
<thead>
|
|
<tr>
|
|
<th>Militante</th>
|
|
<th>Tipo de Pagamento</th>
|
|
<th>Valor</th>
|
|
<th>Data do Pagamento</th>
|
|
<th>Ações</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for pagamento in pagamentos %}
|
|
<tr>
|
|
<td data-militante="{{ pagamento.militante_id }}">{{ pagamento.militante.nome if pagamento.militante else 'N/A' }}</td>
|
|
<td data-tipo="{{ pagamento.tipo_pagamento }}">
|
|
{% if pagamento.tipo_pagamento == 1 %}
|
|
Mensalidade
|
|
{% elif pagamento.tipo_pagamento == 2 %}
|
|
Contribuição Extra
|
|
{% elif pagamento.tipo_pagamento == 3 %}
|
|
Doação
|
|
{% elif pagamento.tipo_pagamento == 4 %}
|
|
Taxa de Evento
|
|
{% elif pagamento.tipo_pagamento == 5 %}
|
|
Outros
|
|
{% else %}
|
|
Não Definido
|
|
{% endif %}
|
|
</td>
|
|
<td data-valor="{{ pagamento.valor }}">R$ {{ "%.2f"|format(pagamento.valor) }}</td>
|
|
<td data-data="{{ pagamento.data_pagamento }}">{{ pagamento.data_pagamento.strftime('%d/%m/%Y') }}</td>
|
|
<td>
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline-primary"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#modalEditarPagamento"
|
|
data-pagamento-id="{{ pagamento.id }}"
|
|
data-militante-id="{{ pagamento.militante_id }}"
|
|
data-tipo-pagamento="{{ pagamento.tipo_pagamento }}"
|
|
data-valor="{{ pagamento.valor }}"
|
|
data-data-pagamento="{{ pagamento.data_pagamento.strftime('%Y-%m-%d') }}"
|
|
title="Editar">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline-danger"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#modalExcluirPagamento"
|
|
data-pagamento-id="{{ pagamento.id }}"
|
|
data-pagamento-info="Pagamento de {{ pagamento.militante.nome if pagamento.militante else 'N/A' }} - R$ {{ "%.2f"|format(pagamento.valor) }}"
|
|
title="Excluir">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Novo Pagamento -->
|
|
<div class="modal fade" id="modalNovoPagamento" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><i class="fas fa-plus"></i> Novo Pagamento</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="formNovoPagamento" method="post" action="{{ url_for('pagamento.novo') }}">
|
|
<div class="mb-3">
|
|
<label for="militante" class="form-label">Militante:</label>
|
|
<select class="form-select" id="militante" name="militante_id" required>
|
|
<option value="">Selecione um militante</option>
|
|
{% for militante in militantes %}
|
|
<option value="{{ militante.id }}">{{ militante.nome }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="tipoPagamento" class="form-label">Tipo de Pagamento:</label>
|
|
<select class="form-select" id="tipoPagamento" name="tipo_pagamento" required>
|
|
<option value="">Selecione o tipo</option>
|
|
<option value="1">Mensalidade</option>
|
|
<option value="2">Contribuição Extra</option>
|
|
<option value="3">Doação</option>
|
|
<option value="4">Taxa de Evento</option>
|
|
<option value="5">Outros</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="valor" class="form-label">Valor:</label>
|
|
<input type="number" step="0.01" class="form-control" id="valor" name="valor" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="dataPagamento" class="form-label">Data do Pagamento:</label>
|
|
<input type="date" class="form-control" id="dataPagamento" name="data_pagamento" required>
|
|
</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</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Editar Pagamento -->
|
|
<div class="modal fade" id="modalEditarPagamento" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><i class="fas fa-edit"></i> Editar Pagamento</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="formEditarPagamento" method="post">
|
|
<div class="mb-3">
|
|
<label for="editMilitante" class="form-label">Militante:</label>
|
|
<input type="text" class="form-control bg-light" id="editMilitanteNome" readonly>
|
|
<input type="hidden" id="editMilitante" name="militante_id">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editTipoPagamento" class="form-label">Tipo de Pagamento:</label>
|
|
<select class="form-select" id="editTipoPagamento" name="tipo_pagamento" required>
|
|
<option value="">Selecione o tipo</option>
|
|
<option value="1">Mensalidade</option>
|
|
<option value="2">Contribuição Extra</option>
|
|
<option value="3">Doação</option>
|
|
<option value="4">Taxa de Evento</option>
|
|
<option value="5">Outros</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editValor" class="form-label">Valor:</label>
|
|
<input type="number" step="0.01" class="form-control" id="editValor" name="valor" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editDataPagamento" class="form-label">Data do Pagamento:</label>
|
|
<input type="date" class="form-control" id="editDataPagamento" name="data_pagamento" required>
|
|
</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</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Excluir Pagamento -->
|
|
<div class="modal fade" id="modalExcluirPagamento" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><i class="fas fa-trash"></i> Excluir Pagamento</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Tem certeza que deseja excluir este pagamento?</p>
|
|
<p id="pagamentoInfo" class="text-muted"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<form id="formExcluirPagamento" method="post">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
|
<button type="submit" class="btn btn-danger">Excluir</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script src="{{ url_for('static', filename='js/pagamentos.js') }}"></script>
|
|
{% endblock %}
|
|
|