Corregidos paginas de creacion
This commit is contained in:
parent
b48058e495
commit
9eb2bd5648
|
@ -87,74 +87,46 @@ class UserFilterForm(FlaskForm):
|
|||
# Rutas
|
||||
@users_bp.route("/")
|
||||
@login_required
|
||||
@permission_required(5000) # Assuming 5000+ is admin level permission
|
||||
@permission_required(1000) # Minimum permission level
|
||||
def list():
|
||||
"""List all users."""
|
||||
# Import here to avoid circular imports
|
||||
from services.user_service import get_all_users
|
||||
|
||||
users = get_all_users()
|
||||
|
||||
return render_template("users/list.html", users=users)
|
||||
|
||||
|
||||
@users_bp.route("/create", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@permission_required(9000) # Solo administradores
|
||||
def create():
|
||||
"""Crear nuevo usuario."""
|
||||
@permission_required(9000) # Admin level permission required
|
||||
def create(): # Changed from create_user to create
|
||||
"""Create a new user."""
|
||||
form = UserForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
# Validar datos
|
||||
data = {
|
||||
"nombre": form.nombre.data,
|
||||
if request.method == "POST" and form.validate_on_submit():
|
||||
try:
|
||||
# Extract user data from form
|
||||
user_data = {
|
||||
"username": form.username.data,
|
||||
"nombre": form.nombre.data,
|
||||
"email": form.email.data,
|
||||
"password": form.password.data,
|
||||
"nivel": form.nivel.data,
|
||||
"idioma": form.idioma.data,
|
||||
"empresa": form.empresa.data,
|
||||
"estado": form.estado.data,
|
||||
"fecha_caducidad": (
|
||||
form.fecha_caducidad.data if form.fecha_caducidad.data else None
|
||||
),
|
||||
"idioma": form.idioma.data,
|
||||
}
|
||||
|
||||
is_valid, errors = validate_user_data(data)
|
||||
# Create the user
|
||||
result = create_user(user_data) # This is a function call, not a route
|
||||
|
||||
if not is_valid:
|
||||
for field, error in errors.items():
|
||||
flash(f"Error en {field}: {error}", "danger")
|
||||
return render_template("users/create.html", form=form)
|
||||
|
||||
# Crear usuario
|
||||
success, message = create_user(
|
||||
username=data["username"],
|
||||
nombre=data["nombre"],
|
||||
email=data["email"],
|
||||
password=data["password"],
|
||||
nivel=data["nivel"],
|
||||
idioma=data["idioma"],
|
||||
fecha_caducidad=data["fecha_caducidad"],
|
||||
empresa=data["empresa"],
|
||||
estado=data["estado"],
|
||||
)
|
||||
|
||||
if success:
|
||||
flash(message, "success")
|
||||
|
||||
# Registrar actividad
|
||||
log_user_management(
|
||||
admin_id=current_user.id,
|
||||
target_user_id=data["username"],
|
||||
action="create",
|
||||
)
|
||||
|
||||
return redirect(url_for("users.list_users"))
|
||||
if result["success"]:
|
||||
flash("Usuario creado exitosamente.", "success")
|
||||
return redirect(url_for("users.list"))
|
||||
else:
|
||||
flash(message, "danger")
|
||||
flash(f'Error al crear usuario: {result["error"]}', "danger")
|
||||
|
||||
except Exception as e:
|
||||
flash(f"Error inesperado: {str(e)}", "danger")
|
||||
|
||||
# If GET request or form validation failed
|
||||
return render_template("users/create.html", form=form)
|
||||
|
||||
|
||||
|
@ -167,7 +139,7 @@ def edit(username):
|
|||
|
||||
if not user:
|
||||
flash(f"Usuario {username} no encontrado.", "danger")
|
||||
return redirect(url_for("users.list_users"))
|
||||
return redirect(url_for("users.list"))
|
||||
|
||||
form = UserForm(obj=user)
|
||||
|
||||
|
@ -207,7 +179,7 @@ def edit(username):
|
|||
details={"fields_updated": list(data.keys())},
|
||||
)
|
||||
|
||||
return redirect(url_for("users.list_users"))
|
||||
return redirect(url_for("users.list"))
|
||||
else:
|
||||
flash(message, "danger")
|
||||
|
||||
|
@ -221,11 +193,11 @@ def delete(username):
|
|||
"""Eliminar usuario."""
|
||||
if username == current_user.id:
|
||||
flash("No puede eliminar su propio usuario.", "danger")
|
||||
return redirect(url_for("users.list_users"))
|
||||
return redirect(url_for("users.list"))
|
||||
|
||||
if username == "admin":
|
||||
flash("No se puede eliminar el usuario administrador.", "danger")
|
||||
return redirect(url_for("users.list_users"))
|
||||
return redirect(url_for("users.list"))
|
||||
|
||||
success, message = delete_user(username)
|
||||
|
||||
|
@ -239,7 +211,7 @@ def delete(username):
|
|||
else:
|
||||
flash(message, "danger")
|
||||
|
||||
return redirect(url_for("users.list_users"))
|
||||
return redirect(url_for("users.list"))
|
||||
|
||||
|
||||
# API para verificar disponibilidad de nombre de usuario
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Crear Proyecto - ARCH{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h1>Crear Nuevo Proyecto</h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="mb-0">Información del Proyecto</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('projects.create') }}">
|
||||
{{ form.csrf_token if form.csrf_token }}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="codigo" class="form-label">Código del Proyecto</label>
|
||||
<input type="text" class="form-control" id="codigo" name="codigo" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="descripcion" class="form-label">Descripción</label>
|
||||
<textarea class="form-control" id="descripcion" name="descripcion" rows="3" required></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="esquema" class="form-label">Esquema</label>
|
||||
<select class="form-select" id="esquema" name="esquema" required>
|
||||
{% if schemas %}
|
||||
{% for codigo, schema in schemas.items() %}
|
||||
<option value="{{ codigo }}">{{ codigo }} - {{ schema.descripcion }}</option>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<option value="">No hay esquemas disponibles</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="cliente" class="form-label">Cliente</label>
|
||||
<input type="text" class="form-control" id="cliente" name="cliente">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="destinacion" class="form-label">Destinación</label>
|
||||
<input type="text" class="form-control" id="destinacion" name="destinacion">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="proyecto_padre" class="form-label">Proyecto Padre (opcional)</label>
|
||||
<select class="form-select" id="proyecto_padre" name="proyecto_padre">
|
||||
<option value="">Ninguno</option>
|
||||
{% if projects %}
|
||||
{% for project in projects %}
|
||||
<option value="{{ project.id }}">{{ project.codigo }} - {{ project.descripcion }}</option>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="estado" class="form-label">Estado</label>
|
||||
<select class="form-select" id="estado" name="estado">
|
||||
<option value="activo" selected>Activo</option>
|
||||
<option value="archivado">Archivado</option>
|
||||
<option value="suspendido">Suspendido</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<button type="submit" class="btn btn-primary">Crear Proyecto</button>
|
||||
<a href="{{ url_for('projects.list') }}" class="btn btn-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,140 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Crear Esquema - ARCH{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h1>Crear Nuevo Esquema</h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="mb-0">Información del Esquema</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('schemas.create') }}" id="schema-form">
|
||||
{{ form.csrf_token if form.csrf_token }}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="codigo" class="form-label">Código del Esquema</label>
|
||||
<input type="text" class="form-control" id="codigo" name="codigo" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="descripcion" class="form-label">Descripción</label>
|
||||
<textarea class="form-control" id="descripcion" name="descripcion" rows="3" required></textarea>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h4>Documentos del Esquema</h4>
|
||||
|
||||
<div id="documents-container">
|
||||
<!-- Initial document template -->
|
||||
<div class="document-item card mb-3 p-3">
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-3">
|
||||
<label class="form-label">Tipo de Documento</label>
|
||||
<select class="form-select" name="doc_tipo[]" required>
|
||||
{% if filetypes %}
|
||||
{% for extension, filetype in filetypes.items() %}
|
||||
<option value="{{ extension }}">{{ filetype.descripcion }}</option>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<option value="">No hay tipos disponibles</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Nombre</label>
|
||||
<input type="text" class="form-control" name="doc_nombre[]" required>
|
||||
</div>
|
||||
<div class="col-md-2 mb-3">
|
||||
<label class="form-label">Nivel Ver</label>
|
||||
<input type="number" class="form-control" name="doc_nivel_ver[]" value="0" min="0" max="9999">
|
||||
</div>
|
||||
<div class="col-md-2 mb-3">
|
||||
<label class="form-label">Nivel Editar</label>
|
||||
<input type="number" class="form-control" name="doc_nivel_editar[]" value="1000" min="0" max="9999">
|
||||
</div>
|
||||
<div class="col-md-1 mb-3 d-flex align-items-end">
|
||||
<button type="button" class="btn btn-danger remove-document" style="display:none;">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<button type="button" class="btn btn-secondary" id="add-document">
|
||||
<i class="fas fa-plus"></i> Agregar Documento
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<button type="submit" class="btn btn-primary">Crear Esquema</button>
|
||||
<a href="{{ url_for('schemas.list') }}" class="btn btn-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const container = document.getElementById('documents-container');
|
||||
const addButton = document.getElementById('add-document');
|
||||
|
||||
// Initially enable the remove button if more than one document exists
|
||||
updateRemoveButtons();
|
||||
|
||||
addButton.addEventListener('click', function() {
|
||||
const documentTemplate = container.querySelector('.document-item').cloneNode(true);
|
||||
|
||||
// Reset values
|
||||
const inputs = documentTemplate.querySelectorAll('input[type="text"], input[type="number"]');
|
||||
inputs.forEach(input => {
|
||||
if (input.name.includes('nivel_ver')) {
|
||||
input.value = '0';
|
||||
} else if (input.name.includes('nivel_editar')) {
|
||||
input.value = '1000';
|
||||
} else {
|
||||
input.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
container.appendChild(documentTemplate);
|
||||
updateRemoveButtons();
|
||||
|
||||
// Add event listener to the new remove button
|
||||
documentTemplate.querySelector('.remove-document').addEventListener('click', function() {
|
||||
this.closest('.document-item').remove();
|
||||
updateRemoveButtons();
|
||||
});
|
||||
});
|
||||
|
||||
// Function to update the visibility of remove buttons
|
||||
function updateRemoveButtons() {
|
||||
const items = container.querySelectorAll('.document-item');
|
||||
items.forEach((item, index) => {
|
||||
const removeBtn = item.querySelector('.remove-document');
|
||||
if (items.length > 1) {
|
||||
removeBtn.style.display = 'block';
|
||||
} else {
|
||||
removeBtn.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add event listeners to initial remove buttons
|
||||
document.querySelectorAll('.remove-document').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
this.closest('.document-item').remove();
|
||||
updateRemoveButtons();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,73 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Crear Usuario - ARCH{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h1>Crear Usuario</h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="mb-0">Información del Usuario</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('users.create') }}">
|
||||
{{ form.csrf_token if form.csrf_token }}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Nombre de Usuario</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="nombre" class="form-label">Nombre Completo</label>
|
||||
<input type="text" class="form-control" id="nombre" name="nombre" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Correo Electrónico</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Contraseña</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password_confirm" class="form-label">Confirmar Contraseña</label>
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="nivel" class="form-label">Nivel de Acceso</label>
|
||||
<select class="form-select" id="nivel" name="nivel" required>
|
||||
<option value="1000">Usuario (1000)</option>
|
||||
<option value="5000">Supervisor (5000)</option>
|
||||
<option value="9000">Administrador (9000)</option>
|
||||
<option value="9999">Super Administrador (9999)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="empresa" class="form-label">Empresa</label>
|
||||
<input type="text" class="form-control" id="empresa" name="empresa" value="ARCH">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="idioma" class="form-label">Idioma</label>
|
||||
<select class="form-select" id="idioma" name="idioma">
|
||||
<option value="es" selected>Español</option>
|
||||
<option value="en">Inglés</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<button type="submit" class="btn btn-primary">Crear Usuario</button>
|
||||
<a href="{{ url_for('users.list') }}" class="btn btn-secondary">Cancelar</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -28,7 +28,8 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user_id, user in users.items() %}
|
||||
{% if users and users|length > 0 %}
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{ user.username }}</td>
|
||||
<td>{{ user.nombre }}</td>
|
||||
|
@ -56,11 +57,12 @@
|
|||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center">No hay usuarios registrados.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@
|
|||
"ESQ001": {
|
||||
"codigo": "ESQ001",
|
||||
"descripcion": "Proyecto estándar",
|
||||
"fecha_creacion": "2025-03-04T10:17:09.979764+00:00",
|
||||
"fecha_creacion": "2025-03-04T10:25:03.799581+00:00",
|
||||
"creado_por": "admin",
|
||||
"documentos": [
|
||||
{
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
"nombre": "Administrador",
|
||||
"username": "admin",
|
||||
"email": "admin@example.com",
|
||||
"password_hash": "$2b$04$MDmmt/Wr5K0vEpL0I2gfVOQb6af8xHtympw8lbDUjuTA8mY4wEJ7K",
|
||||
"password_hash": "$2b$04$UGmPF4BBNejhS7ZKA58/hu3A8DtXkx7/Fyw.8igRby6eDw/RwkvAq",
|
||||
"nivel": 9999,
|
||||
"idioma": "es",
|
||||
"fecha_caducidad": null,
|
||||
"empresa": "",
|
||||
"estado": "activo",
|
||||
"ultimo_acceso": "2025-03-04T10:17:09.978287+00:00"
|
||||
"ultimo_acceso": "2025-03-04T10:25:03.799581+00:00"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue