🎮 Controladores - Plugin Coches

Gestionan la lógica de negocio y las interacciones del usuario con los vehículos

📋 Controladores del Plugin Coches

✏️

EditCoche.php

Controlador para crear y editar vehículos individuales

EditController
📋

ListCoche.php

Controlador para listar, buscar y gestionar múltiples vehículos

ListController

✏️ EditCoche.php - Controlador de Edición

Controller/EditCoche.php
<?php
namespace FacturaScripts\Plugins\Coches\Controller;

use FacturaScripts\Core\Lib\ExtendedController\EditController;

class EditCoche extends EditController
{
    public function getModelClassName(): string
    {
        return 'Coche';
    }
}

🎯 Simplicidad y Eficiencia

Este controlador es minimalista porque hereda toda la funcionalidad de EditController:

  • Creación automática de formularios desde vistas XML
  • Validación de datos integrada según el modelo
  • Guardado y actualización automáticos con transacciones
  • Manejo de errores y mensajes al usuario
  • Integración automática con vistas XML del modelo

🔗 Conexión con el Modelo

El método getModelClassName() es crucial:

  • Define qué modelo gestiona este controlador: 'Coche'
  • Permite la comunicación automática con la base de datos
  • Habilita las operaciones CRUD básicas automáticamente
  • Conecta con la vista XML correspondiente (EditCoche.xml)
  • Establece las reglas de validación según las propiedades del modelo

📋 ListCoche.php - Controlador de Listado

Controller/ListCoche.php
<?php
namespace FacturaScripts\Plugins\Coches\Controller;

use FacturaScripts\Core\Lib\ExtendedController\ListController;
use FacturaScripts\Dinamic\Model\Coche;
use FacturaScripts\Core\Tools;

class ListCoche extends ListController
{
    public function getPageData(): array
    {
        $page = parent::getPageData();
        $page['title'] = 'Coches';
        $page['menu'] = 'Coches';
        $page['icon'] = 'fas fa-search';
        return $page;
    }

    protected function createViews()
    {
        $this->addView('ListCoche', 'coche', 'coche', 'fas fa-car')
            ->addOrderBy(['idcoche'], 'Creacion', 2)
            ->addSearchFields(['matricula', 'marca', 'modelo']);

        $this->setSettings('ListCoche', 'modalInsert', 'modalCoche');

        $this->addButton('ListCoche',[
            'action' => 'siniestro',
            'type' => 'action',
            'icon' => 'fas fa-exclamation-triangle',
            'label' => 'Baja',
            'color' => 'danger',
            'confirm' => true,
        ]);

        $this->addButton('ListCoche',[
            'action' => 'fechaitv',
            'type' => 'modal',
            'icon' => 'fas fa-exclamation-triangle',
            'label' => 'ITV',
            'color' => 'warning',
            'confirm' => true,
        ]);
    }

    protected function execPreviousAction($action)
    {
        switch($action){
            case 'siniestro':
                $this->siniestro();
                break;
            case 'fechaitv':
                $this->fechaitv();
                break;
            case 'modalCoche':
                $this->modalCoche();
                break;
        }
        return parent::execPreviousAction($action);
    }

    protected function siniestro()
    {
        $codes = $this->request->request->getArray('codes');
        if (empty($codes)){
            Tools::log()->warning('No se han seleccionado coches para marcar como siniestro.');
            return;
        }
        foreach ($codes as $code) {
            $coche = new Coche();
            $coche = $coche->find($code);
            $coche->siniestro=true;
            $coche->save();
            Tools::log()->notice('Marcado como siniestro los coches seleccionados.');
        }
    }

    protected function fechaitv()
    {
        $codes = $this->request->request->getArray('codes');
        if (empty($codes)){
            Tools::log()->warning('No se han seleccionado coches para cambiar la ITV.');
            return;
        }
        foreach ($codes as $code) {
            $coche = new Coche();
            $coche = $coche->find($code);
            $coche->fechaitv = $this->request->request->get('fechaitv');
            $coche->save();
            Tools::log()->notice('ITV cambiada de los coches seleccionados.');
        }
    }

    protected function modalCoche()
    {
        $coche = new Coche();
        $coche->matricula = $this->request->request->get('matricula');
        $coche->marca = $this->request->request->get('marca');
        $coche->modelo = $this->request->request->get('modelo');
        $coche->fechaitv = $this->request->request->get('fechaitv');
        $coche->siniestro = false;
        $coche->save();
        Tools::log()->notice('Vehículo creado con éxito.');
    }
}

🔍 Análisis de ListCoche.php

📊 getPageData() - Configuración de Página

public function getPageData(): array
{
    $page = parent::getPageData();
    $page[\'title\'] = \'Coches\';
    $page[\'menu\'] = \'Coches\';
    $page[\'icon\'] = \'fas fa-search\';
    return $page;
}

Función: Configura los metadatos de la página del controlador

  • title: 'Coches' - Título que aparece en el navegador
  • menu: 'Coches' - Menú donde aparece la opción en FacturaScripts
  • icon: 'fas fa-search' - Icono de FontAwesome para el menú
  • parent::getPageData(): Obtiene configuración base del controlador padre

👁️ createViews() - Configuración de Vistas

protected function createViews()
{
    $this->addView(\'ListCoche\', \'coche\', \'coche\', \'fas fa-car\')
        ->addOrderBy([\'idcoche\'], \'Creacion\', 2)
        ->addSearchFields([\'matricula\', \'marca\', \'modelo\']);

    $this->setSettings(\'ListCoche\', \'modalInsert\', \'modalCoche\');

    $this->addButton(\'ListCoche\',[
        \'action\' => \'siniestro\',
        \'type\' => \'action\',
        \'icon\' => \'fas fa-exclamation-triangle\',
        \'label\' => \'Baja\',
        \'color\' => \'danger\',
        \'confirm\' => true,
    ]);

    $this->addButton(\'ListCoche\',[
        \'action\' => \'fechaitv\',
        \'type\' => \'modal\',
        \'icon\' => \'fas fa-exclamation-triangle\',
        \'label\' => \'ITV\',
        \'color\' => \'warning\',
        \'confirm\' => true,
    ]);
}

Parámetros de addView:

  • ViewName: 'ListCoche' - Nombre interno de la vista
  • ModelName: 'coche' - Nombre del modelo (en minúsculas)
  • ViewTitle: 'coche' - Título que ven los usuarios
  • ViewIcon: 'fas fa-car' - Icono de la vista

Configuraciones adicionales:

  • addOrderBy(): Campos para ordenar (idcoche por creación)
  • addSearchFields(): Campos para búsqueda (matrícula, marca, modelo)
  • setSettings(): Configura modal para inserción rápida
  • addButton(): Añade botones de acción personalizados

⚡ execPreviousAction() - Acciones Personalizadas

protected function execPreviousAction($action){
    switch($action){
        case "siniestro":
            $this->siniestro();
            break;
        case "fechaitv":
            $this->fechaitv();
            break;
        case "modalCoche":
            $this->modalCoche();
            break;
    }
    return parent::execPreviousAction($action);
}

Función: Maneja acciones personalizadas desde los botones de la vista

Flujo de ejecución:

  1. El usuario hace clic en un botón de acción en la vista XML
  2. Se ejecuta execPreviousAction() con el nombre de la acción
  3. El switch detecta la acción y llama al método correspondiente
  4. Si no hay coincidencia, delega al padre con parent::execPreviousAction()
  5. Los métodos llamados procesan la lógica específica

🛠️ Acciones Personalizadas del Controlador

🚨 siniestro() - Marcar como Baja

protected function siniestro()
{
    $codes = $this->request->request->getArray(\'codes\');
    if (empty($codes)){
        Tools::log()->warning(\'No se han seleccionado coches...\');
        return;
    }
    foreach ($codes as $code) {
        $coche = new Coche();
        $coche = $coche->find($code);
        $coche->siniestro=true;
        $coche->save();
    }
    Tools::log()->notice(\'Marcado como siniestro...\');
}

Función: Marca los vehículos seleccionados como siniestrados

Flujo de ejecución:

  1. Obtiene los IDs seleccionados con getArray('codes')
  2. Valida que haya selección, si no, muestra warning
  3. Para cada ID: crea instancia, busca el coche, marca siniestro=true
  4. Guarda cada cambio con save()
  5. Registra mensaje de éxito en el log del sistema
⚠️ Característica: Botón con confirm: true pide confirmación antes de ejecutar

📅 fechaitv() - Cambiar Fecha ITV

protected function fechaitv()
{
    $codes = $this->request->request->getArray(\'codes\');
    if (empty($codes)){
        Tools::log()->warning(\'No se han seleccionado coches...\');
        return;
    }
    foreach ($codes as $code) {
        $coche = new Coche();
        $coche = $coche->find($code);
        $coche->fechaitv = $this->request->request->get(\'fechaitv\');
        $coche->save();
    }
    Tools::log()->notice(\'ITV cambiada...\');
}

Función: Actualiza la fecha ITV de vehículos seleccionados

Flujo de ejecución:

  1. Obtiene los IDs seleccionados
  2. Valida selección
  3. Para cada ID: busca coche, actualiza fecha ITV desde request
  4. Guarda cambios
  5. Registra en log
💡 Característica especial: Tipo modal - abre ventana emergente para ingresar fecha

🚗 modalCoche() - Creación Rápida

protected function modalCoche()
{
    $coche = new Coche();
    $coche->matricula = $this->request->request->get(\'matricula\');
    $coche->marca = $this->request->request->get(\'marca\');
    $coche->modelo = $this->request->request->get(\'modelo\');
    $coche->fechaitv = $this->request->request->get(\'fechaitv\');
    $coche->siniestro = false;
    $coche->save();
    Tools::log()->notice(\'Vehículo creado con éxito.\');
}

Función: Crea un nuevo vehículo desde modal de inserción rápida

Flujo de ejecución:

  1. Crea nueva instancia de Coche
  2. Asigna valores desde el formulario modal
  3. Establece siniestro = false por defecto
  4. Guarda el nuevo registro
  5. Registra mensaje de éxito
Ventaja: Permite crear vehículos sin salir del listado principal

🔗 Integración con Vistas XML

🎮
Controlador
ListCoche.php
📋
Vista XML
ListCoche.xml
🖥️
Interfaz
de Usuario
👤
Usuario
Final

Conexión Botones → Acciones

Vista XML - Botón de Acción

<button action="siniestro" 
        color="danger" 
        icon="fas fa-exclamation-triangle" 
        label="Baja" 
        type="action" 
        confirm="true"/>

Controlador PHP - Switch Case

case "siniestro":
    $this->siniestro();
    break;

Conectores automáticos: El atributo action en el botón XML se conecta automáticamente con el case correspondiente en execPreviousAction().

Configuración de Modal de Inserción

Controlador PHP - Configuración

$this->setSettings(\'ListCoche\', 
    \'modalInsert\', 
    \'modalCoche\');

Vista XML - Definición del Modal

<modals>
    <group name="modalCoche" 
           title="Modelo de Coche" 
           icon="fas fa-car">
        <!-- campos del modal -->
    </group>
</modals>

Integración automática: El controlador configura qué modal usar para inserción rápida, y la vista XML define la estructura del modal.

🎯 Buenas Prácticas Implementadas

🔒 Validación de Datos

Todas las acciones validan la entrada antes de procesar:

if (empty($codes)){
    Tools::log()->warning(\'No se han seleccionado...\');
    return;
}

Evita errores y proporciona feedback al usuario.

📝 Logs Informativos

Uso consistente del sistema de logs de FacturaScripts:

Tools::log()->warning(\'Mensaje de advertencia\');
Tools::log()->notice(\'Mensaje informativo\');
Tools::log()->error(\'Mensaje de error\');

Facilita debugging y seguimiento de operaciones.

🔄 Gestión de Errores

Patrón de early return para manejar errores:

if ($condicionError) {
    Tools::log()->warning(\'Error detectado\');
    return; // Sale temprano sin ejecutar más código
}
// Código normal aquí...

Mantiene el código limpio y fácil de leer.

⚠️ Problemas Comunes y Soluciones

Acciones no se ejecutan

Causa: Nombre de acción no coincide entre XML y PHP

Solución: Verificar que action="nombre" en XML coincida exactamente con case "nombre": en PHP (case-sensitive)

Modal no aparece

Causa: Nombre del modal mal configurado o no existe en XML

Solución: Verificar que setSettings('modalInsert', 'nombreModal') coincida con name="nombreModal" en XML

No se procesan múltiples registros

Causa: Método getArray('codes') no retorna datos

Solución: Verificar que en la vista XML los registros estén seleccionables y se envíen correctamente

🚀 Mejoras Recomendadas

Validación de Matrículas

protected function validarMatricula($matricula): bool
{
    // Formato español: 1234ABC
    return preg_match(\'/^\d{4}[A-Z]{3}$/\', $matricula);
}

protected function modalCoche()
{
    $matricula = $this->request->request->get(\'matricula\');
    if (!$this->validarMatricula($matricula)) {
        Tools::log()->error(\'Formato de matrícula inválido\');
        return;
    }
    // ... resto del código
}

Agregar validaciones específicas para datos de vehículos.

Acciones Asíncronas

protected function siniestro()
{
    $codes = $this->request->request->getArray(\'codes\');
    $total = count($codes);
    $procesados = 0;
    
    foreach ($codes as $code) {
        // Procesar cada coche
        $procesados++;
        
        // Enviar progreso al cliente
        $this->toolBox()->i18nLog()->info(
            \'Procesando: \' . $procesados . \'/\' . $total
        );
    }
}

Para muchas operaciones, mostrar progreso al usuario.

Permisos Específicos

public function getPageData(): array
{
    $page = parent::getPageData();
    // ... configuración
    
    // Restringir acceso según permisos
    if (!$this->user->can(\'edit-coches\')) {
        $page[\'show\'] = false;
    }
    
    return $page;
}

Agregar control de permisos para acciones críticas.

🧪 Demo: Flujo de Ejecución Completo

1

Usuario selecciona vehículos

En la lista, el usuario marca checkboxes de varios coches

2

Click en botón "Baja"

Usuario hace clic en botón rojo con icono de exclamación

3

Confirmación modal

Aparece modal pidiendo confirmación (confirm="true")

4

Ejecución siniestro()

Controlador obtiene IDs, valida, actualiza cada coche, guarda cambios

5

Feedback visual

Coches aparecen en rojo en la lista, log registra la acción

💡 Abre la consola del navegador para ver la simulación paso a paso