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
95 lines
3.7 KiB
HTML
95 lines
3.7 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{% block title %}Novo Material{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<h1 class="mb-4">Novo Material</h1>
|
|
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ category }}">{{ message }}</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<form method="POST" class="needs-validation" novalidate>
|
|
<div class="mb-3">
|
|
<label for="nome" class="form-label">Nome</label>
|
|
<input type="text" class="form-control" id="nome" name="nome" required>
|
|
<div class="invalid-feedback">
|
|
Por favor, insira o nome do material.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="descricao" class="form-label">Descrição</label>
|
|
<textarea class="form-control" id="descricao" name="descricao" rows="3" required></textarea>
|
|
<div class="invalid-feedback">
|
|
Por favor, insira a descrição do material.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="preco" class="form-label">Preço</label>
|
|
<input type="number" class="form-control" id="preco" name="preco" step="0.01" required>
|
|
<div class="invalid-feedback">
|
|
Por favor, insira o preço do material.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="quantidade" class="form-label">Quantidade</label>
|
|
<input type="number" class="form-control" id="quantidade" name="quantidade" required>
|
|
<div class="invalid-feedback">
|
|
Por favor, insira a quantidade do material.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="tipo_id" class="form-label">Tipo de Material</label>
|
|
<select class="form-select" id="tipo_id" name="tipo_id" required>
|
|
<option value="">Selecione um tipo</option>
|
|
{% for tipo in tipos %}
|
|
<option value="{{ tipo.id }}">{{ tipo.nome }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<div class="invalid-feedback">
|
|
Por favor, selecione o tipo do material.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-between">
|
|
<button type="submit" class="btn btn-success">Registrar</button>
|
|
<a href="{{ url_for('material.listar') }}" class="btn btn-outline-secondary">Voltar</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Validação do formulário
|
|
(function () {
|
|
'use strict'
|
|
|
|
var forms = document.querySelectorAll('.needs-validation')
|
|
|
|
Array.prototype.slice.call(forms)
|
|
.forEach(function (form) {
|
|
form.addEventListener('submit', function (event) {
|
|
if (!form.checkValidity()) {
|
|
event.preventDefault()
|
|
event.stopPropagation()
|
|
}
|
|
|
|
form.classList.add('was-validated')
|
|
}, false)
|
|
})
|
|
})()
|
|
</script>
|
|
{% endblock %}
|