from flask import ( Blueprint, render_template, redirect, url_for, flash, request, jsonify, current_app, ) from flask_login import login_required, current_user from flask_wtf import FlaskForm from wtforms import ( StringField, TextAreaField, FieldList, FormField, SelectField, IntegerField, SubmitField, ) from wtforms.validators import DataRequired, Length, NumberRange from services.schema_service import ( get_all_schemas, get_schema_by_id, create_schema, update_schema, delete_schema, ) from services.document_service import get_allowed_filetypes from utils.security import permission_required from utils.validators import validate_schema_data # Definir Blueprint schemas_bp = Blueprint("schemas", __name__, url_prefix="/schemas") # Formularios class DocumentTypeForm(FlaskForm): """Formulario para tipo de documento en esquema.""" tipo = StringField("Tipo de Documento", validators=[DataRequired()]) nombre = StringField("Nombre", validators=[DataRequired()]) nivel_ver = IntegerField("Nivel para Ver", default=0) nivel_editar = IntegerField("Nivel para Editar", default=5000) class SchemaForm(FlaskForm): """Formulario para esquema.""" codigo = StringField("Código", validators=[DataRequired(), Length(1, 20)]) descripcion = TextAreaField("Descripción", validators=[DataRequired()]) documentos = FieldList(FormField(DocumentTypeForm), min_entries=1) submit = SubmitField("Guardar") # Rutas @schemas_bp.route("/") @login_required @permission_required(5000) # Nivel mínimo para ver esquemas def list(): """Lista todos los esquemas disponibles.""" schemas = get_all_schemas() return render_template("schemas/list.html", schemas=schemas) @schemas_bp.route("/view/") @login_required @permission_required(5000) def view(schema_id): """Ver detalle de un esquema.""" schema = get_schema_by_id(schema_id) if not schema: flash("Esquema no encontrado.", "danger") return redirect(url_for("schemas.list")) return render_template("schemas/view.html", schema=schema) @schemas_bp.route("/create", methods=["GET", "POST"]) @login_required @permission_required(9000) # Solo administradores def create(): """Crear nuevo esquema.""" form = SchemaForm() if form.validate_on_submit(): data = { "codigo": form.codigo.data, "descripcion": form.descripcion.data, "documentos": [], } for doc_form in form.documentos: data["documentos"].append( { "tipo": doc_form.tipo.data, "nombre": doc_form.nombre.data, "nivel_ver": doc_form.nivel_ver.data, "nivel_editar": doc_form.nivel_editar.data, } ) success, message = create_schema(data, current_user.id) if success: flash(message, "success") return redirect(url_for("schemas.list")) else: flash(message, "danger") return render_template("schemas/create.html", form=form) @schemas_bp.route("/edit/", methods=["GET", "POST"]) @login_required def edit_schema(schema_id): schema = get_schema_by_id(schema_id) if not schema: flash("Esquema no encontrado", "danger") return redirect(url_for("schemas.list")) filetypes = get_allowed_filetypes() if request.method == "POST": # Extract form data nombre = request.form.get("nombre") descripcion = request.form.get("descripcion") # Update schema data updated_schema = { "id": schema_id, "nombre": nombre, "descripcion": descripcion, "created_by": schema.get("created_by"), "created_at": schema.get("created_at"), "documentos": schema.get("documentos", []), } success = update_schema(schema_id, updated_schema) if success: flash("Esquema actualizado correctamente", "success") return redirect(url_for("schemas.list")) else: flash("Error al actualizar el esquema", "danger") return render_template("schemas/edit.html", schema=schema, filetypes=filetypes) @schemas_bp.route("/delete/", methods=["POST"]) @login_required @permission_required(9000) # Solo administradores def delete(schema_id): """Eliminar esquema.""" success, message = delete_schema(schema_id) if success: flash(message, "success") else: flash(message, "danger") return redirect(url_for("schemas.list")) @schemas_bp.route("/api/list") @login_required def api_list(): """API para listar esquemas.""" schemas = get_all_schemas() return jsonify( [ {"code": code, "description": schema["descripcion"]} for code, schema in schemas.items() ] ) @schemas_bp.route("/api/get/") @login_required def api_get(schema_code): """API para obtener un esquema específico.""" schema = get_schema_by_id(schema_code) if not schema: return jsonify({"error": "Esquema no encontrado"}), 404 return jsonify(schema)