feat: implementa sistema de comprovantes com centralizações e PIX
This commit is contained in:
@@ -541,8 +541,8 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ url_for('listar_pagamentos') }}">
|
||||
<i class="fas fa-receipt"></i>Pagamentos
|
||||
<a class="dropdown-item" href="{{ url_for('listar_comprovantes') }}">
|
||||
<i class="fas fa-receipt"></i>Comprovantes
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -563,8 +563,8 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ url_for('listar_assinaturas') }}">
|
||||
<i class="fas fa-file-signature"></i>Assinaturas
|
||||
<a class="dropdown-item" href="{{ url_for('listar_vendas_jornal') }}">
|
||||
<i class="fas fa-file-signature"></i>Assinaturas de Jornal
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="stats-card yellow">
|
||||
<div class="title">Assinaturas Ativas</div>
|
||||
<div class="value">{{ total_assinaturas }}</div>
|
||||
<a href="{{ url_for('listar_assinaturas') }}" class="link">
|
||||
<a href="{{ url_for('listar_vendas_jornal') }}" class="link">
|
||||
Ver detalhes <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
<div class="icon">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h2><i class="fas fa-money-bill-wave"></i> Comprovantes</h2>
|
||||
<div>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalNovoComprovante">
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#novoComprovanteModal">
|
||||
<i class="fas fa-plus"></i> Novo Comprovante
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" id="btnExportar">
|
||||
@@ -22,40 +22,30 @@
|
||||
<table class="table table-striped table-hover" id="tabelaComprovantes">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Militante</th>
|
||||
<th>Tipo de Comprovante</th>
|
||||
<th>Valor</th>
|
||||
<th>Data do Comprovante</th>
|
||||
<th>Data</th>
|
||||
<th>Forma de Pagamento</th>
|
||||
<th>Campanha</th>
|
||||
<th>Centralizações</th>
|
||||
<th>Ações</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for comprovante in comprovantes %}
|
||||
<tr>
|
||||
<td data-militante="{{ comprovante.militante_id }}">{{ comprovante.militante.nome if comprovante.militante else 'N/A' }}</td>
|
||||
<td data-tipo="{{ comprovante.tipo_comprovante }}">
|
||||
{% if comprovante.tipo_comprovante == 1 %}
|
||||
Cota
|
||||
{% elif comprovante.tipo_comprovante == 2 %}
|
||||
Contribuição Extra
|
||||
{% elif comprovante.tipo_comprovante == 3 %}
|
||||
Doação
|
||||
{% elif comprovante.tipo_comprovante == 4 %}
|
||||
Taxa de Evento
|
||||
{% elif comprovante.tipo_comprovante == 5 %}
|
||||
Jornal Avulso
|
||||
{% elif comprovante.tipo_comprovante == 6 %}
|
||||
Assinatura de Jornal
|
||||
{% elif comprovante.tipo_comprovante == 7 %}
|
||||
Campanha Financeira
|
||||
{% elif comprovante.tipo_comprovante == 8 %}
|
||||
Outros
|
||||
{% else %}
|
||||
Não Definido
|
||||
{% endif %}
|
||||
<td>{{ comprovante.id }}</td>
|
||||
<td>{{ comprovante.militante.nome }}</td>
|
||||
<td>{{ comprovante.data_comprovante.strftime('%d/%m/%Y') }}</td>
|
||||
<td>{{ comprovante.forma_pagamento }}</td>
|
||||
<td>{{ comprovante.campanha.nome if comprovante.campanha else '-' }}</td>
|
||||
<td>
|
||||
<ul class="list-unstyled">
|
||||
{% for centralizacao in comprovante.centralizacoes %}
|
||||
<li>{{ centralizacao.tipo_comprovante }}: R$ {{ "%.2f"|format(centralizacao.valor) }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</td>
|
||||
<td data-valor="{{ comprovante.valor }}">R$ {{ "%.2f"|format(comprovante.valor) }}</td>
|
||||
<td data-data="{{ comprovante.data_comprovante }}">{{ comprovante.data_comprovante.strftime('%d/%m/%Y') }}</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-primary"
|
||||
@@ -63,8 +53,7 @@
|
||||
data-bs-target="#modalEditarComprovante"
|
||||
data-comprovante-id="{{ comprovante.id }}"
|
||||
data-militante-id="{{ comprovante.militante_id }}"
|
||||
data-tipo-comprovante="{{ comprovante.tipo_comprovante }}"
|
||||
data-valor="{{ comprovante.valor }}"
|
||||
data-militante-nome="{{ comprovante.militante.nome }}"
|
||||
data-data-comprovante="{{ comprovante.data_comprovante.strftime('%Y-%m-%d') }}"
|
||||
title="Editar">
|
||||
<i class="fas fa-edit"></i>
|
||||
@@ -74,7 +63,7 @@
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modalExcluirComprovante"
|
||||
data-comprovante-id="{{ comprovante.id }}"
|
||||
data-comprovante-info="Comprovante de {{ comprovante.militante.nome if comprovante.militante else 'N/A' }} - R$ {{ "%.2f"|format(comprovante.valor) }}"
|
||||
data-comprovante-info="Comprovante de {{ comprovante.militante.nome }} - Total: R$ {{ "%.2f"|format(comprovante.centralizacoes|sum(attribute='valor')) }}"
|
||||
title="Excluir">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
@@ -89,58 +78,159 @@
|
||||
</div>
|
||||
|
||||
<!-- Modal Novo Comprovante -->
|
||||
<div class="modal fade" id="modalNovoComprovante" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal fade" id="novoComprovanteModal" tabindex="-1" aria-labelledby="novoComprovanteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-plus"></i> Novo Comprovante</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
<h5 class="modal-title" id="novoComprovanteModalLabel">Novo Comprovante</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="formNovoComprovante" method="post" action="{{ url_for('adicionar_comprovante') }}">
|
||||
<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>
|
||||
<form id="novoComprovanteForm">
|
||||
<!-- Dados únicos do comprovante -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="militante_id" class="form-label">Militante</label>
|
||||
<select class="form-select" id="militante_id" name="militante_id" required>
|
||||
<option value="">Selecione o militante</option>
|
||||
{% for militante in militantes %}
|
||||
<option value="{{ militante.id }}">{{ militante.nome }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="data_comprovante" class="form-label">Data do Comprovante</label>
|
||||
<input type="date" class="form-control" id="data_comprovante" name="data_comprovante" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="tipoComprovante" class="form-label">Tipo de Comprovante:</label>
|
||||
<select class="form-select" id="tipoComprovante" name="tipo_comprovante" required>
|
||||
<option value="">Selecione o tipo</option>
|
||||
<option value="1">Cota</option>
|
||||
{% if current_user.has_permission('gerenciar_tipos_comprovante') %}
|
||||
<option value="2">Contribuição Extra</option>
|
||||
<option value="3">Doação</option>
|
||||
<option value="4">Taxa de Evento</option>
|
||||
<option value="5">Jornal Avulso</option>
|
||||
<option value="6">Assinatura de Jornal</option>
|
||||
<option value="7">Campanha Financeira</option>
|
||||
<option value="8">Outros</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="forma_pagamento" class="form-label">Forma de Pagamento</label>
|
||||
<select class="form-select" id="forma_pagamento" name="forma_pagamento" required>
|
||||
<option value="">Selecione a forma de pagamento</option>
|
||||
<option value="PIX">PIX</option>
|
||||
<option value="TRANSFERENCIA">Transferência/DOC</option>
|
||||
<option value="DEPOSITO">Depósito</option>
|
||||
<option value="MAQUININHA">Maquininha</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="campanha_id" class="form-label">Campanha</label>
|
||||
<select class="form-select" id="campanha_id" name="campanha_id">
|
||||
<option value="">Selecione a campanha</option>
|
||||
{% for campanha in campanhas %}
|
||||
<option value="{{ campanha.id }}">{{ campanha.nome }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</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="dataComprovante" class="form-label">Data do Comprovante:</label>
|
||||
<input type="date" class="form-control" id="dataComprovante" name="data_comprovante" 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>
|
||||
|
||||
<!-- Centralizações -->
|
||||
<div class="centralizacoes-container">
|
||||
<h6 class="mb-3">Centralizações</h6>
|
||||
<div class="centralizacao-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Tipo de Comprovante</label>
|
||||
<select class="form-select tipo-comprovante" name="tipo_comprovante[]" required>
|
||||
<option value="">Selecione o tipo</option>
|
||||
<option value="COTA">Cota</option>
|
||||
<option value="JORNAL">Jornal</option>
|
||||
<option value="ASSINATURA">Assinatura</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Valor</label>
|
||||
<input type="number" class="form-control valor" name="valor[]" step="0.01" required>
|
||||
</div>
|
||||
<div class="col-md-1 d-flex align-items-end">
|
||||
<button type="button" class="btn btn-danger btn-sm remover-centralizacao">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary btn-sm mb-3" id="adicionar-centralizacao">
|
||||
<i class="bi bi-plus"></i> Adicionar Centralização
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="button" class="btn btn-primary" id="salvarComprovante">Salvar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.centralizacao-item {
|
||||
background-color: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Adicionar nova centralização
|
||||
document.getElementById('adicionar-centralizacao').addEventListener('click', function() {
|
||||
const container = document.querySelector('.centralizacoes-container');
|
||||
const newItem = document.querySelector('.centralizacao-item').cloneNode(true);
|
||||
newItem.querySelector('.valor').value = '';
|
||||
newItem.querySelector('.tipo-comprovante').value = '';
|
||||
container.appendChild(newItem);
|
||||
});
|
||||
|
||||
// Remover centralização
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.closest('.remover-centralizacao')) {
|
||||
const centralizacoes = document.querySelectorAll('.centralizacao-item');
|
||||
if (centralizacoes.length > 1) {
|
||||
e.target.closest('.centralizacao-item').remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Salvar comprovante
|
||||
document.getElementById('salvarComprovante').addEventListener('click', function() {
|
||||
const form = document.getElementById('novoComprovanteForm');
|
||||
const formData = new FormData(form);
|
||||
|
||||
// Coletar dados das centralizações
|
||||
const centralizacoes = [];
|
||||
document.querySelectorAll('.centralizacao-item').forEach(item => {
|
||||
centralizacoes.push({
|
||||
tipo_comprovante: item.querySelector('.tipo-comprovante').value,
|
||||
valor: item.querySelector('.valor').value
|
||||
});
|
||||
});
|
||||
|
||||
// Adicionar centralizações ao formData
|
||||
formData.append('centralizacoes', JSON.stringify(centralizacoes));
|
||||
|
||||
fetch('/comprovantes/novo', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Erro ao salvar comprovante');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('Erro ao salvar comprovante');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Modal Editar Comprovante -->
|
||||
<div class="modal fade" id="modalEditarComprovante" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-4">
|
||||
<input type="text" class="form-control" id="otp" name="otp" placeholder="Código OTP" required>
|
||||
<input type="text" class="form-control" id="otp" name="otp" placeholder="Código OTP">
|
||||
<label for="otp">Código OTP</label>
|
||||
<div class="invalid-feedback">
|
||||
Por favor, informe o código OTP.
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary">Registrar</button>
|
||||
<a href="{{ url_for('listar_assinaturas') }}" class="btn btn-secondary">Voltar</a>
|
||||
<a href="{{ url_for('listar_vendas_jornal') }}" class="btn btn-secondary">Voltar</a>
|
||||
<a href="{{ url_for('home') }}" class="btn btn-outline-primary">Início</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user