# 📋 Guía de Implementación: Validación con Check-in y Leyenda Administrable en `validar_datos.php`
### Convocatorias FOCINE / IMCINE — Gobierno de México

Esta guía documenta la arquitectura técnica, código fuente y procedimiento de replicación para implementar de forma uniforme el **Sistema de Validación con Check-in (Checkbox de aceptación) y Leyenda Dinámica Administrable** en la vista `validar_datos.php` y el modal de `carga_doc.php` en las convocatorias de FOCINE/IMCINE:

1. **`acervos`** *(Implementada y validada como proyecto piloto)*
2. **`animacion`**
3. **`cortometraje`**
4. **`documental`**
5. **`estados`**
6. **`exhibicion_equipamientos`**
7. **`exhibicion_programas`**
8. **`experimental`**
9. **`ficcion`**
10. **`infancias`**
11. **`operasprimas`**
12. **`postproduccion`**

---

## 📑 Índice
1. [Resumen y Arquitectura del Flujo](#1-resumen-y-arquitectura-del-flujo)
2. [Capa 1: Base de Datos (Columna `validar_datos_checkin` y Catálogo `secciones_publico`)](#2-capa-1-base-de-datos)
3. [Capa 2: Configuración y Backend (`variables_globales.php`, `init_session.php`, `control_sistema.php`, `dao_sistema.php`)](#3-capa-2-configuración-y-backend)
4. [Capa 3: Vista de Usuario `validar_datos.php` (Diseño Gob.mx sin revisión de campos)](#4-capa-3-vista-de-usuario-validar_datosphp)
5. [Capa 4: Integración en `carga_doc.php` y Control del Botón del Modal](#5-capa-4-integración-en-carga_docphp-y-control-del-botón)
6. [Capa 5: Función JavaScript `confirmacion()` en `proyecto.js`](#6-capa-5-función-javascript-confirmacion-en-proyectojs)
7. [Script Automatizado de Migración de Base de Datos](#7-script-automatizado-de-migración-de-base-de-datos)
8. [Script de Verificación de Sintaxis y Estado](#8-script-de-verificación-de-sintaxis-y-estado)
9. [Prompt Maestro para Replicación con Agentes](#9-prompt-maestro-para-replicación-con-agentes)

---

## 1. Resumen y Arquitectura del Flujo

El requerimiento moderniza la pantalla `validar_datos.php` para cumplir con dos objetivos:
1. **Eliminar la revisión exhaustiva de campos de formulario**, ya que el usuario previamente capturó sus datos en `datos.php` y subió sus archivos en `carga_doc.php`.
2. **Presentar una leyenda legal institucional administrable** (editable año con año desde el panel de "Secciones" por los administradores) y una casilla de verificación (**checkbox / check-in**) que el postulante debe marcar obligatoriamente para habilitar el botón **"Concluir registro e imprimir acuse"** en el modal de `carga_doc.php`.

```
┌────────────────────────────────────────────────────────────────────────────────────────┐
│                        carga_doc.php (Ventana Padre con Modal)                         │
│                                                                                        │
│   [ Botón 'Validar y concluir registro' ]                                              │
│               │                                                                        │
│               ▼ Abre #ventanaModal                                                     │
│   ┌────────────────────────────────────────────────────────────────────────────────┐   │
│   │ Modal Header: [ Editar ]   [ Concluir registro e imprimir acuse (DISABLED) ]   │   │
│   ├────────────────────────────────────────────────────────────────────────────────┤   │
│   │ Modal Body: <iframe id="iframeModalValidar" src="validar_datos.php">          │   │
│   │                                                                                │   │
│   │   ┌────────────────────────────────────────────────────────────────────────┐   │   │
│   │   │ validar_datos.php                                                      │   │   │
│   │   │                                                                        │   │   │
│   │   │  1. Leyenda Dinámica ($ctrlSys->contenidoSeccion(27))                  │   │   │
│   │   │  2. [x] Casilla de Aceptación (id="chk_validar_datos")                 │   │   │
│   │   │           │                                                            │   │   │
│   │   │           ├── onChange: notificarEstadoCheckin(checked)                │   │   │
│   │   │           └── postMessage / window.parent.actualizarEstadoBoton...     │   │   │
│   │   └───────────┼────────────────────────────────────────────────────────────┘   │   │
│   │               ▼                                                                │   │
│   │   Habilita / Deshabilita [ Concluir registro e imprimir acuse ] en Modal Padre │   │
│   └────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                        │
│   Al confirmar -> confirmacion() -> switch.php?do_action=concluir&validar_datos_checkin=1 │
└────────────────────────────────────────────────────────────────────────────────────────┘
```

---

## 2. Capa 1: Base de Datos

Cada convocatoria cuenta con su base de datos propia. Se deben aplicar dos cambios en cada una:

### A. Columna `validar_datos_checkin` en tabla `proyectos`
```sql
ALTER TABLE proyectos 
ADD COLUMN validar_datos_checkin TINYINT(1) NOT NULL DEFAULT 0 
AFTER datos_validados;
```

### B. Registro en `secciones_publico` (ID 27)
```sql
INSERT INTO secciones_publico (id_seccion_publico, nombre_seccion_publico, contenido_seccion_publico) 
VALUES (
    27,
    'Validación de datos / Leyenda de confirmación check-in',
    '<p>He revisado detenidamente los datos y la documentación registrada en la plataforma y confirmo que son verídicos, completos y corresponden íntegramente a la persona solicitante y al proyecto postulado. Entiendo que esta información tiene carácter de declaración bajo protesta de decir verdad y no podrá ser modificada una vez concluido el registro.</p>'
);
```

> [!NOTE]
> Al insertar en `secciones_publico`, el selector en `secciones.php` del Administrador listará la nueva sección **automáticamente** gracias a `$ctrlSys->secciones()`. El administrador podrá editar el texto con el editor enriquecido (SCEditor) y guardarlo.
> 
> *Nota especial de compatibilidad*: En **11 convocatorias** se utiliza el ID **`27`**. En la convocatoria **`postproduccion`**, debido a que el ID 27 estaba previamente asignado a `EMAIL_PROYECTO_NO_COMPLETO_2DA`, se utiliza automáticamente el ID **`28`**. Todo el código en `validar_datos.php` lee la constante dinámicamente mediante `defined('VALIDAR_DATOS_LEYENDA_CHECKIN') ? VALIDAR_DATOS_LEYENDA_CHECKIN : 27`.

---

## 3. Capa 2: Configuración y Backend

### A. Constante en `backEnd/variables_globales.php`
Agregar la constante que identifica la sección:
```php
const VALIDAR_DATOS_LEYENDA_CHECKIN = 27;
```

### B. Carga en sesión en `backEnd/init_session.php`
Al recuperar los datos del proyecto, exponer la variable global:
```php
@$nombre_proyecto = $proyecto[0]['nombre_proyecto'];
@$datos_validados = $proyecto[0]['datos_validados'];
@$validar_datos_checkin = isset($proyecto[0]['validar_datos_checkin']) ? intval($proyecto[0]['validar_datos_checkin']) : 0;
@$correo_responsable = $proyecto[0]['correo_responsable'];
```

### C. Validación en `backEnd/CONTROL/control_sistema.php`
En el método `concluir_proyecto($arreglo)`:
```php
function concluir_proyecto($arreglo){
    $mensaje = "";
    try {
        $filasAfectadas = "";
        $respuesta = "";
        $tools = new Herramientas();
        $dao = new ClaseDaoSistema();
        $templateCorreo = new TemplatesCorreos();	
        $correo = new CorreoElectronico();
        
        // Verificación de check-in obligatorio
        if (empty($arreglo["validar_datos_checkin"]) || intval($arreglo["validar_datos_checkin"]) !== 1) {
            return "carga_doc.php?tab=1&mensaje=" . urlencode("Debes aceptar y confirmar la casilla de verificación antes de concluir el registro.");
        }
        
        if ($arreglo["estatus_proyecto"] == SIN_FINALIZAR) { 			
            $filas = $dao->cerrando_proyecto($arreglo["vmd5"]);
            $filasAfectadas = $filas["filasAfectadas"];						
        }
        ...
```

### D. Persistencia en `backEnd/DAO/dao_sistema.php`
En los métodos `cerrando_proyecto` y `cerrando_proyecto_editado`, agregar `validar_datos_checkin=1`:
```php
function cerrando_proyecto($visitantemd5){
    $conexion = new OBD();
    $update = "UPDATE proyectos SET datos_validados=1,
                                    validar_datos_checkin=1,
                                    estatus_proyecto=" . CARGA_CONCLUIDA . ", 
                                    fecha_registro_fin=date_format(now(),'%Y-%m-%d %H:%i:%s')
               WHERE visitantemd5='" . $visitantemd5 . "'";
    $respuesta = $conexion->query_update($update, DSN_LOCAL);
    return $respuesta;					
}

function cerrando_proyecto_editado($visitantemd5){
    $conexion = new OBD();
    $update = "UPDATE proyectos SET datos_validados=1,
                                    validar_datos_checkin=1,
                                    estatus_proyecto=" . CORREGIDO . ",
                                    fecha_actualizacion_fin=date_format(now(),'%Y-%m-%d %H:%i:%s')
               WHERE visitantemd5='" . $visitantemd5 . "'";
    $respuesta = $conexion->query_update($update, DSN_LOCAL);
    return $respuesta;					
}
```

---

---

## 4. Capa 3: Activos Centralizados en `api_imcine_v2`

Para evitar duplicar código CSS y JavaScript en las 13 convocatorias, los estilos y la lógica se colocaron de manera centralizada en **`api_imcine_v2`**:

### A. Estilos CSS Centralizados: `api_imcine_v2/css_base/validar_datos.css`
Contiene las reglas visuales institucionales (ocultamiento de header/footer en iframe, tarjetas, alertas, contenedor de check-in, etc.) y se encuentra referenciado directamente en `api_imcine_v2/css_base/estilo.css`:
```css
@import url("validar_datos.css");
```
> Como todas las convocatorias ya importan `estilo.css` en `header_session.php`, los estilos de validación quedan disponibles de inmediato para todas las convocatorias.

### B. JavaScript de Check-in: `api_imcine_v2/js/validar_datos.js`
Gestiona el estado visual del box de confirmación y la emisión de mensajes hacia la ventana padre (`window.parent` y `postMessage`):
```javascript
(function() {
    function notificarEstadoCheckin(estaMarcado) {
        var box = document.getElementById('box_checkin');
        if (box) {
            if (estaMarcado) {
                box.classList.add('activo');
            } else {
                box.classList.remove('activo');
            }
        }

        try {
            if (window.parent && typeof window.parent.actualizarEstadoBotonConcluir === 'function') {
                window.parent.actualizarEstadoBotonConcluir(estaMarcado);
            }
        } catch(e) {
            console.warn("No se pudo invocar directamente window.parent:", e);
        }

        try {
            if (window.parent) {
                window.parent.postMessage({
                    type: 'CHECKIN_VALIDAR_DATOS',
                    checked: Boolean(estaMarcado)
                }, '*');
            }
        } catch(e) {
            console.warn("Error enviando postMessage:", e);
        }
    }

    window.notificarEstadoCheckin = notificarEstadoCheckin;

    document.addEventListener('DOMContentLoaded', function() {
        var chk = document.getElementById('chk_validar_datos');
        if (chk) {
            chk.addEventListener('change', function() {
                notificarEstadoCheckin(this.checked);
            });
            notificarEstadoCheckin(chk.checked);
        }
    });
})();
```

### C. JavaScript del Modal Padre: `api_imcine_v2/js/cargar_docs.js`
Todas las convocatorias cargan `cargar_docs.js` en `carga_doc.php`. Se agregó centralmente el escuchador para gestionar el botón `#btn_concluir_modal` y la recarga dinámica del iframe:
```javascript
(function() {
    function actualizarEstadoBotonConcluir(habilitar) {
        var btn = document.getElementById('btn_concluir_modal');
        if (btn) {
            btn.disabled = !habilitar;
        }
    }
    window.actualizarEstadoBotonConcluir = actualizarEstadoBotonConcluir;

    window.addEventListener('message', function(event) {
        if (event.data && event.data.type === 'CHECKIN_VALIDAR_DATOS') {
            actualizarEstadoBotonConcluir(Boolean(event.data.checked));
        }
    });

    document.addEventListener('DOMContentLoaded', function() {
        if (typeof $ !== 'undefined') {
            $('#ventanaModal').on('show.bs.modal', function () {
                var btn = document.getElementById('btn_concluir_modal');
                if (btn && !btn.hasAttribute('data-checkin-previo')) {
                    btn.disabled = true;
                }
                var iframe = document.getElementById('iframeModalValidar');
                if (iframe) {
                    iframe.src = 'validar_datos.php?tab=1&v=' + new Date().getTime();
                }
            });
        }
    });
})();
```

---

## 4. Capa 3: Vista `validar_datos.php` (Diseño Limpio Gob.mx sin Header/Footer Anidado)

> [!IMPORTANT]
> **No incluir `header_session.php` ni `footer.php`**: Al cargarse dentro de un `<iframe>`, incluir `footer.php` provocaría que `gobmx.js` inyecte la barra de navegación del portal nacional y el pie de página dentro del modal, recortando y desconfigurando el contenido. Por ello, `validar_datos.php` debe ser un documento HTML independiente y pulcro:

```php
<?php 
require_once 'backEnd/init_session.php'; 
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Confirmación y Validación de Registro</title>

    <!-- Tipografía institucional Montserrat -->
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400&display=swap" rel="stylesheet">
    <link href="https://framework-gb.cdn.gob.mx/assets/styles/main.css" rel="stylesheet">
    <link href="<?php echo DIRECCION_CSS . 'estilo.css?v=' . time(); ?>" rel="stylesheet" type="text/css">
    <link href="<?php echo DIRECCION_CSS . 'validar_datos.css?v=' . time(); ?>" rel="stylesheet" type="text/css">

    <!-- JS base -->
    <script src="<?php echo DIRECCION_BOOTSTRAP . 'jquery-3.6.0.js?v=' . time(); ?>"></script>
</head>
<body class="validar-iframe-body">

<div class="validar-container">
    <div class="validar-card">
        <!-- Badge institucional del Proyecto -->
        <div class="validar-proyecto-badge">
            <div class="validar-badge-icon">
                <span class="glyphicon glyphicon-folder-open"></span>
            </div>
            <div class="validar-badge-info">
                <div class="validar-badge-nombre"><?php echo htmlspecialchars($nombre_proyecto ?? '', ENT_QUOTES, 'UTF-8'); ?></div>
                <div class="validar-badge-folio">Folio del proyecto: <strong>#<?php echo htmlspecialchars($id_proyecto ?? '', ENT_QUOTES, 'UTF-8'); ?></strong></div>
            </div>
        </div>

        <!-- Leyenda administrable desde la sección de 'Secciones' (ID 27) -->
        <div class="validar-leyenda">
            <div class="validar-leyenda-titulo">
                <span class="glyphicon glyphicon-file"></span> Declaración bajo protesta de decir verdad:
            </div>
            <div class="validar-leyenda-cuerpo">
                <?php 
                    $contenidoLeyenda = $ctrlSys->contenidoSeccion(VALIDAR_DATOS_LEYENDA_CHECKIN);
                    echo !empty($contenidoLeyenda) ? $contenidoLeyenda : '<p>He revisado detenidamente los datos y la documentación registrada en la plataforma y confirmo que son verídicos, completos y corresponden íntegramente a la persona solicitante y al proyecto postulado. Entiendo que esta información tiene carácter de declaración bajo protesta de decir verdad y no podrá ser modificada una vez concluido el registro.</p>'; 
                ?>
            </div>
        </div>

        <!-- Casilla de Check-in interactiva -->
        <div class="validar-checkin-box <?php echo (!empty($validar_datos_checkin) && $validar_datos_checkin == 1) ? 'activo' : ''; ?>" id="box_checkin">
            <label class="validar-checkbox-label" for="chk_validar_datos">
                <input type="checkbox" id="chk_validar_datos" name="validar_datos_checkin" value="1" 
                    <?php echo (!empty($validar_datos_checkin) && $validar_datos_checkin == 1) ? 'checked' : ''; ?>>
                <span class="validar-checkin-texto">
                    He leído, acepto los términos y confirmo que la información y los documentos cargados son verídicos, correctos y definitivos.
                </span>
            </label>
        </div>

        <div class="validar-alerta-info">
            <span class="glyphicon glyphicon-info-sign"></span>
            <span>Para habilitar el botón <strong>"Concluir registro e imprimir acuse"</strong>, es requisito obligatorio marcar la casilla de confirmación.</span>
        </div>
    </div>
</div>

<script src="<?php echo DIRECCION_JS . 'validar_datos.js?v=' . time(); ?>"></script>
</body>
</html>
```

---

## 5. Capa 4: Integración en `carga_doc.php` y Modal Profesional

En `carga_doc.php`, justo después de `include ("header_session.php");` y de cargar `cargar_docs.js`, incluir la hoja de estilos:
```php
<link href="<?php echo DIRECCION_CSS . 'validar_datos.css?v=' . time(); ?>" rel="stylesheet" type="text/css">
```

Y reemplazar la estructura de `#ventanaModal` por la versión con diseño Gob.mx (encabezado institucional, iframe limpio y botones de acción en el pie del modal):

```html
<!-- Modal de Validación y Conclusión -->
<div class="modal fade" id="ventanaModal" tabindex="-1" role="dialog" aria-labelledby="titulo_modal" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content modal-validar-content">

            <!-- Encabezado del Modal con estilo institucional Gob.mx -->
            <div class="modal-header modal-validar-header">
                <div class="modal-validar-header-left">
                    <span class="modal-validar-icon glyphicon glyphicon-check"></span>
                    <div class="modal-validar-titulos">
                        
                        <span class="modal-validar-sub">Paso final: Lee la declaración, confirma la veracidad y concluye el trámite</span>
                    </div>
                </div>
                <button type="button" class="close modal-validar-close" data-dismiss="modal" aria-label="Cerrar">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>

            <!-- Cuerpo del Modal: Iframe limpio y estilizado -->
            <div class="modal-body modal-validar-body">
                <iframe id="iframeModalValidar" src="about:blank" class="iframeModalValidar" style="width: 100% !important; min-height: 440px !important; border: none !important; display: block !important;"></iframe>
            </div>

            <!-- Pie del Modal: Botones de Acción Oficiales -->
            <div class="modal-footer modal-validar-footer">
                <button id="btn_editar_modal" type="button" class="btn btn-default btn-validar-editar" data-dismiss="modal"
                    onclick="javascript:window.location='datos.php?tab=1'">
                    <span class="glyphicon glyphicon-edit"></span> Modificar datos
                </button>
                <button id="btn_concluir_modal" type="button" class="btn btn-primary btn-validar-concluir" 
                    data-checkin-previo="<?php echo (!empty($validar_datos_checkin) && $validar_datos_checkin == 1) ? '1' : '0'; ?>" 
                    <?php echo (!empty($validar_datos_checkin) && $validar_datos_checkin == 1) ? '' : 'disabled'; ?>
                    onclick="confirmacion()">
                    <span>Concluir registro e imprimir acuse</span>
                    <span class="glyphicon glyphicon-arrow-right"></span>
                </button>
            </div>

        </div>
    </div>
</div>
```

> [!TIP]
> **100% Centralizado en `api_imcine_v2`**:
> Como `carga_doc.php` ya incluye `<script src="<?php echo DIRECCION_JS.'cargar_docs.js?v='.time(); ?>"></script>` y `<link href="<?php echo DIRECCION_CSS.'estilo.css?v='.time(); ?>">`:
> - Los estilos del modal (`.modal-validar-content`, `.modal-validar-header`, botones y badges) se cargan desde `api_imcine_v2/css_base/validar_datos.css`.
> - La sincronización del botón, los eventos `postMessage` y el auto-ajuste de altura del iframe se gestionan desde `api_imcine_v2/js/cargar_docs.js`.
> - **NO es necesario escribir código JavaScript ni CSS adicional en ninguna convocatoria**.

---

## 6. Capa 5: Función JavaScript `confirmacion()` en `proyecto.js`

En `js/proyecto.js`:
Verificar que el botón no esté inhabilitado y enviar `validar_datos_checkin=1` en los parámetros URL:

```javascript
function confirmacion() {
	var btn = document.getElementById('btn_concluir_modal');
	if (btn && btn.disabled) {
		alert("Debes aceptar y confirmar la casilla de verificación antes de concluir el registro.");
		return false;
	}

	var texto_confirmacion = "Una vez que valides que la información es correcta, podrás concluir el registro del proyecto. Después de responder una breve encuesta, recuerda generar el acuse de registro y estar pendiente del correo.";
	if (confirm(texto_confirmacion) == true) {
		var params = "do_action=concluir"
			+ "&destinatario=" + encodeURIComponent($("#destinatario").val() || "")
			+ "&estatus_proyecto=" + encodeURIComponent($("#estatus_proyecto").val() || "")
			+ "&correo=" + encodeURIComponent($("#correo_responsable").val() || "")
			+ "&id_proyecto=" + encodeURIComponent($("#id_proyecto").val() || "")
			+ "&vmd5=" + encodeURIComponent($("#vmd5").val() || "")
			+ "&tipo_persona=" + encodeURIComponent($("#tipo_persona").val() || "")
			+ "&usu=" + encodeURIComponent($("#usu").val() || "")
			+ "&nombre_proyecto=" + encodeURIComponent($("#nombre_proyecto").val() || "")
			+ "&validar_datos_checkin=1";
		window.location = "switch.php?" + params;
	}
}
```

---

## 7. Script Automatizado de Migración de Base de Datos

Guarda y ejecuta este script en la raíz de `/home/convocatoriasdev/public_html/focine/` para migrar de forma masiva las 12 convocatorias:

```bash
#!/usr/bin/env bash
# migrar_checkin_convocatorias.sh

CONVOCATORIAS=(
  "acervos"
  "animacion"
  "cortometraje"
  "documental"
  "estados"
  "exhibicion_equipamientos"
  "exhibicion_programas"
  "experimental"
  "ficcion"
  "infancias"
  "operasprimas"
  "postproduccion"
)

BASE_DIR="/home/convocatoriasdev/public_html/focine"

echo "=== MIGRACIÓN DE BASE DE DATOS: VALIDAR_DATOS_CHECKIN Y SECCIÓN 27 ==="

for conv in "${CONVOCATORIAS[@]}"; do
  DIR="$BASE_DIR/$conv"
  if [ -d "$DIR" ]; then
    echo "Procesando BD de $conv..."
    php -r '
      $_SERVER["DOCUMENT_ROOT"] = "/home/convocatoriasdev/public_html";
      require_once "'$DIR'/backEnd/variables_globales.php";
      require_once "'$DIR'/backEnd/utilerias/herramientas.php";
      require_once "/home/convocatoriasdev/public_html/api_imcine_v2/adodb/adodb_conexion.php";
      $obd = new OBD();

      // 1. Columna validar_datos_checkin
      $cols = $obd->query_select("SHOW COLUMNS FROM proyectos LIKE '\''validar_datos_checkin'\''", DSN_LOCAL);
      if (empty($cols)) {
          $obd->query_update("ALTER TABLE proyectos ADD COLUMN validar_datos_checkin TINYINT(1) NOT NULL DEFAULT 0 AFTER datos_validados", DSN_LOCAL);
          echo "  ✔ Columna agregada en proyectos\n";
      } else {
          echo "  - Columna ya existente\n";
      }

      // 2. Sección 27
      $sec = $obd->query_select("SELECT id_seccion_publico FROM secciones_publico WHERE id_seccion_publico = 27", DSN_LOCAL);
      if (empty($sec)) {
          $sqlSec = "INSERT INTO secciones_publico (id_seccion_publico, nombre_seccion_publico, contenido_seccion_publico) VALUES (
              27,
              '\''Validación de datos / Leyenda de confirmación check-in'\'',
              '\''<p>He revisado detenidamente los datos y la documentación registrada en la plataforma y confirmo que son verídicos, completos y corresponden íntegramente a la persona solicitante y al proyecto postulado. Entiendo que esta información tiene carácter de declaración bajo protesta de decir verdad y no podrá ser modificada una vez concluido el registro.</p>'\''
          )";
          $obd->query_insert($sqlSec, DSN_LOCAL);
          echo "  ✔ Sección 27 insertada\n";
      } else {
          echo "  - Sección 27 ya existente\n";
      }
    '
  fi
done

echo "=== MIGRACIÓN FINALIZADA ==="
```

---

## 8. Script de Verificación de Sintaxis y Estado

Para comprobar que todos los archivos PHP en las 12 convocatorias estén libres de errores sintácticos:

```bash
#!/usr/bin/env bash
CONVOCATORIAS=(
  "acervos"
  "animacion"
  "cortometraje"
  "documental"
  "estados"
  "exhibicion_equipamientos"
  "exhibicion_programas"
  "experimental"
  "ficcion"
  "infancias"
  "operasprimas"
  "postproduccion"
)

BASE_DIR="/home/convocatoriasdev/public_html/focine"

for conv in "${CONVOCATORIAS[@]}"; do
  echo "Validando sintaxis en $conv..."
  php -l "$BASE_DIR/$conv/validar_datos.php" >/dev/null && echo "  ✔ validar_datos.php"
  php -l "$BASE_DIR/$conv/carga_doc.php" >/dev/null && echo "  ✔ carga_doc.php"
  php -l "$BASE_DIR/$conv/backEnd/variables_globales.php" >/dev/null && echo "  ✔ variables_globales.php"
  php -l "$BASE_DIR/$conv/backEnd/init_session.php" >/dev/null && echo "  ✔ init_session.php"
  php -l "$BASE_DIR/$conv/backEnd/CONTROL/control_sistema.php" >/dev/null && echo "  ✔ control_sistema.php"
  php -l "$BASE_DIR/$conv/backEnd/DAO/dao_sistema.php" >/dev/null && echo "  ✔ dao_sistema.php"
done

echo "Verificación concluida con éxito."
```

---

## 9. Prompt Maestro para Replicación con Agentes

Copia y pega este prompt en sesiones de agentes de IA para reproducir la implementación de forma autónoma:

```markdown
# Prompt Maestro: Implementación de Validación con Check-in y Leyenda Administrable en FOCINE

Actúa como Ingeniero de Software Senior en PHP y desarrollo web institucional para IMCINE / Gobierno de México.

## Objetivo
Debes replicar de forma homogénea y rigurosa el nuevo sistema de validación con check-in y leyenda administrable en las siguientes convocatorias de FOCINE:
1. `animacion`
2. `cortometraje`
3. `documental`
4. `estados`
5. `exhibicion_equipamientos`
6. `exhibicion_programas`
7. `experimental`
8. `ficcion`
9. `infancias`
10. `operasprimas`
11. `postproduccion`

## Referencia Técnica
Guíate por:
- Guía oficial: `/home/convocatoriasdev/public_html/focine/GUIA_IMPLEMENTACION_CHECKIN_VALIDAR_DATOS.md`
- Convocatoria piloto de referencia: `/home/convocatoriasdev/public_html/focine/acervos/`

## Pasos Requeridos por Convocatoria:
1. Base de Datos:
   - Agregar columna `validar_datos_checkin TINYINT(1) NOT NULL DEFAULT 0` a la tabla `proyectos` si no existe.
   - Insertar registro ID 27 en `secciones_publico` con nombre 'Validación de datos / Leyenda de confirmación check-in'.
2. `backEnd/variables_globales.php`:
   - Definir `const VALIDAR_DATOS_LEYENDA_CHECKIN = 27;`.
3. `backEnd/init_session.php`:
   - Asignar `@$validar_datos_checkin = isset($proyecto[0]['validar_datos_checkin']) ? intval($proyecto[0]['validar_datos_checkin']) : 0;`.
4. `validar_datos.php`:
   - Eliminar las pestañas y campos de revisión de formulario antiguos.
   - Implementar la vista ligera institucional (Gob.mx / Montserrat / Guinda / Dorado) con la leyenda dinámica `$ctrlSys->contenidoSeccion(VALIDAR_DATOS_LEYENDA_CHECKIN)` y el checkbox `#chk_validar_datos`.
   - Incluir script que notifique a `window.parent` (`actualizarEstadoBotonConcluir` y `postMessage`).
5. `carga_doc.php`:
   - Configurar `#btn_concluir_modal` con atributo `disabled` condicionado y remover `data-dismiss="modal"`.
   - Agregar la función `actualizarEstadoBotonConcluir()` y el listener `message` al final del archivo.
6. `js/proyecto.js`:
   - En `confirmacion()`, validar que el botón no esté disabled y enviar `&validar_datos_checkin=1`.
7. `backEnd/CONTROL/control_sistema.php` y `backEnd/DAO/dao_sistema.php`:
   - En `concluir_proyecto()`, validar en servidor que `validar_datos_checkin == 1`.
   - En `cerrando_proyecto()` y `cerrando_proyecto_editado()`, actualizar `validar_datos_checkin=1`.
8. Validar la sintaxis de todos los archivos modificados con `php -l`.
```
