Files
erp-efintel-2026-portainer/templates/expenses/gestion.html
T

214 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'base.html' %}
{% block content %}
<div class="header-section" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
<h1>Panel de Gestión Administrativa</h1>
</div>
<div class="glass-card tabs-container" style="padding: 2rem;">
<nav class="tabs-nav">
<button class="tab-btn active" onclick="switchTab(event, 'tab-proyectos')">📁 Proyectos</button>
<button class="tab-btn" onclick="switchTab(event, 'tab-responsables')">👥 Colaboradores / Responsables</button>
<button class="tab-btn" onclick="switchTab(event, 'tab-config')">⚙️ Configuración</button>
<button class="tab-btn" onclick="switchTab(event, 'tab-bitacora')">📜 Bitácora de Auditoría</button>
</nav>
<!-- Pestaña Proyectos -->
<div id="tab-proyectos" class="tab-content active">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
<h2>Proyectos del Sistema</h2>
<a href="{% url 'project_create' %}" class="btn btn-primary">➕ Nuevo Proyecto</a>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>Encargado (Responsable)</th>
<th>Creado Por</th>
<th>Última Modificación</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{% for project in projects %}
<tr>
<td style="font-weight: 600; color: var(--accent-secondary);">{{ project.name }}</td>
<td>{{ project.description|default:"Sin descripción" }}</td>
<td>
{% if project.manager %}
<span style="font-weight: 500;">{{ project.manager.username }}</span>
{% else %}
<em style="color: var(--text-secondary);">No asignado</em>
{% endif %}
</td>
<td>{{ project.created_by.username|default:"Sistema" }}</td>
<td>{{ project.updated_at|date:"d/m/Y H:i" }}</td>
<td>
<div style="display: flex; gap: 0.5rem;">
<a href="{% url 'project_edit' project.id %}" class="btn btn-outline" style="padding: 0.35rem 0.75rem; font-size: 0.8rem;">✏️ Editar</a>
<form action="{% url 'project_delete' project.id %}" method="POST" style="display: inline;" onsubmit="return confirm('¿Estás seguro de que deseas eliminar este proyecto? Se eliminarán todos los gastos asociados.');">
{% csrf_token %}
<button type="submit" class="btn btn-danger" style="padding: 0.35rem 0.75rem; font-size: 0.8rem;">🗑️ Eliminar</button>
</form>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="6" style="text-align: center;">No hay proyectos registrados.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Pestaña Responsables -->
<div id="tab-responsables" class="tab-content">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
<h2>Responsables y Colaboradores</h2>
<a href="{% url 'responsable_create' %}" class="btn btn-primary">➕ Nuevo Responsable</a>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Usuario</th>
<th>Correo</th>
<th>Rol / Permiso</th>
<th>Descripción / Bio</th>
<th>F. Registro</th>
<th>F. Modificación</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{% for resp in responsables %}
<tr>
<td style="font-weight: 600; color: var(--text-primary);">{{ resp.username }}</td>
<td>{{ resp.email|default:"-" }}</td>
<td>
{% if resp.groups.all %}
{% with role=resp.groups.all.0.name %}
{% if role == 'Administrador' %}
<span class="badge badge-admin">Administrador</span>
{% elif role == 'Director de Proyecto' %}
<span class="badge badge-director">Director</span>
{% else %}
<span class="badge badge-gestor">Gestor</span>
{% endif %}
{% endwith %}
{% else %}
<span class="badge badge-gestor">Sin Rol</span>
{% endif %}
</td>
<td>{{ resp.profile.description|default:"Sin descripción personal" }}</td>
<td>{{ resp.profile.created_at|date:"d/m/Y"|default:"-" }}</td>
<td>{{ resp.profile.updated_at|date:"d/m/Y H:i"|default:"-" }}</td>
<td>
<div style="display: flex; gap: 0.5rem;">
<a href="{% url 'responsable_edit' resp.id %}" class="btn btn-outline" style="padding: 0.35rem 0.75rem; font-size: 0.8rem;">✏️ Editar</a>
{% if resp != request.user %}
<form action="{% url 'responsable_delete' resp.id %}" method="POST" style="display: inline;" onsubmit="return confirm('¿Estás seguro de que deseas eliminar este responsable?');">
{% csrf_token %}
<button type="submit" class="btn btn-danger" style="padding: 0.35rem 0.75rem; font-size: 0.8rem;">🗑️ Eliminar</button>
</form>
{% endif %}
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="7" style="text-align: center;">No hay responsables registrados.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Pestaña Configuración -->
<div id="tab-config" class="tab-content">
<div style="margin-bottom: 1.5rem;">
<h2>Configuración General del Sistema</h2>
</div>
<div style="max-width: 500px; display: flex; flex-direction: column; gap: 1.5rem;">
<div class="glass-card" style="padding: 1.5rem; background: rgba(0, 0, 0, 0.2);">
<div style="color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 0.5rem;">Presupuesto General Asignado</div>
<div style="font-size: 2rem; font-weight: 700; color: var(--accent-secondary);">${{ settings.global_budget|default:"100000.00" }}</div>
</div>
<div>
<a href="{% url 'settings_edit' %}" class="btn btn-primary">✏️ Modificar Presupuesto General</a>
</div>
</div>
</div>
<!-- Pestaña Bitácora -->
<div id="tab-bitacora" class="tab-content">
<div style="margin-bottom: 1.5rem;">
<h2>Bitácora de Auditoría y Trazabilidad (Logs)</h2>
<p style="color: var(--text-secondary); font-size: 0.9rem;">Historial detallado de operaciones realizadas por los administradores en el sistema.</p>
</div>
<div class="log-list">
{% for log in logs %}
<div class="log-item">
<div class="log-info">
<div class="log-action">
{% if "Creado" in log.action or "Creación" in log.action %}
🟢 {{ log.action }}
{% elif "Eliminado" in log.action or "Eliminación" in log.action %}
🔴 {{ log.action }}
{% else %}
🟡 {{ log.action }}
{% endif %}
</div>
<div class="log-desc">{{ log.description }}</div>
</div>
<div class="log-meta">
<div style="font-weight: 500; color: var(--accent-primary);">@{{ log.user.username|default:"Sistema" }}</div>
<div style="font-size: 0.75rem; color: var(--text-secondary); margin-top: 0.25rem;">{{ log.timestamp|date:"d/m/Y H:i:s" }}</div>
</div>
</div>
{% empty %}
<div style="text-align: center; color: var(--text-secondary); padding: 2rem;">No hay registros en la bitácora de auditoría.</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
function switchTab(evt, tabId) {
// Ocultar todos los contenidos de pestaña
const contents = document.querySelectorAll('.tab-content');
contents.forEach(content => content.classList.remove('active'));
// Desactivar todos los botones de pestaña
const buttons = document.querySelectorAll('.tab-btn');
buttons.forEach(btn => btn.classList.remove('active'));
// Activar pestaña actual
document.getElementById(tabId).classList.add('active');
evt.currentTarget.classList.add('active');
// Guardar la pestaña activa en localStorage
localStorage.setItem('activeTab', tabId);
}
// Restaurar pestaña activa al cargar la página
document.addEventListener("DOMContentLoaded", function() {
const activeTab = localStorage.getItem('activeTab');
if (activeTab && document.getElementById(activeTab)) {
const btn = Array.from(document.querySelectorAll('.tab-btn')).find(b => b.getAttribute('onclick').includes(activeTab));
if (btn) {
// Simular clic en el botón
btn.click();
}
}
});
</script>
{% endblock %}