# CRUD-L

Una aplicación que gestiona datos utiliza ampliamente las operaciones CRUD-L (Create, Read, Update, Delete y List).

El marco de desarrollo CRUD-L de Devkron facilita y automatiza la implementación de estas operaciones sobre las entidades de datos del sistema.

CRUD-L está implementado según el patrón MVC <a href="https://en.wikipedia.org/wiki/Model-view-controller" target="_blank">Model View Controller</a>

<img src="img/crud-l-mvc.svg">

## Alcance del marco

CRUD-L es una **capa genérica**. Conviene tener presente qué resuelve y qué deja a la capa que lo consume.

**Lo que hace:**

* Determina la operación (create, read, update, delete, list) a partir del método HTTP, la presencia del identificador y el encabezado `Accept`.
* Establece la conexión a la base de datos, incluida la suplantación de identidad a partir de una sesión ya resuelta.
* Implementa las cinco operaciones sobre tablas que siguen el patrón de diseño de Devkron (Induxsoft TableModel).
* Gestiona entidades maestro-detalle dentro de una transacción.
* Selecciona y renderiza la vista apropiada, en HTML o en JSON.

**Lo que no hace:**

* No implementa autorización granular. No verifica privilegios por operación, por entidad ni por campo. Los permisos efectivos sobre los datos son los que el motor de base de datos concede a la identidad de la conexión.
* No recupera por sí mismo el identificador de sesión. Espera que la capa de autorización ya lo haya resuelto.
* No impone un modelo de acciones, eventos ni reglas de negocio.
* No impone bloqueo pesimista. El campo `sys_lock` y las funciones asociadas están disponibles, pero establecer y retirar los bloqueos corresponde al modelo específico si la entidad lo requiere.

Los sistemas construidos sobre CRUD-L añaden estas capacidades por su cuenta. V12, por ejemplo, define su propio modelo de acciones, privilegios y eventos sobre modelos derivados del modelo genérico de CRUD-L; ese modelo pertenece a V12 y no al marco.

## Contenido

1. [Instalación y configuración](crudl/instalacion.md)
2. [Enrutamiento y enmascaramiento de URL](crudl/enrutamiento.md)
3. [El controlador](crudl/controlador.md)
4. [Conexión a la base de datos y sesión](crudl/conexion-y-sesion.md)
5. [Implementación del modelo](crudl/modelo.md)
6. [Entidades maestro-detalle](crudl/maestro-detalle.md)
7. [Implementación de las vistas](crudl/vistas.md)
8. [Patrón PRG y redirección](crudl/prg-y-redireccion.md)
9. [Web services REST](crudl/rest.md)
10. [Archivo de configuración `.crudl`](crudl/configuracion.md)
11. [Referencia de parámetros y variables](crudl/referencia.md)

## Flujo general

<img src="img/flujo-controlador-mvc-crudl.svg"/>

La solicitud HTTP se resuelve en seis fases:

1. **Análisis de la solicitud.** Se recogen los parámetros de URL, el cuerpo de la solicitud y el encabezado `Accept`.
2. **Selección de modelo.** Se busca un `model.dk` en la carpeta de la entidad; si no existe se usa el modelo genérico.
3. **Establecimiento de la conexión.** Ver [Conexión a la base de datos y sesión](crudl/conexion-y-sesion.md).
4. **Realización de la operación.** Se invoca el puntero de función correspondiente.
5. **Selección de la vista.** Según el encabezado `Accept` y el resultado de la operación.
6. **Generación de la respuesta.** HTML o JSON.

## Selección de operación

La operación se determina por el método HTTP y por la presencia del parámetro `_entity_id` en la URL:

<table class="table">
<thead>
<tr>
    <th>Método</th>
    <th>...{_entities_type}/</th>
    <th>...{_entities_type}/{_entity_id}</th>
</tr>
</thead>
<tbody>
<tr>
    <td>GET</td>
    <td>list</td>
    <td>read</td>
</tr>
<tr>
    <td>POST</td>
    <td>create</td>
    <td>error</td>
</tr>
<tr>
    <td>PUT</td>
    <td>error</td>
    <td>update</td>
</tr>
<tr>
    <td>PATCH</td>
    <td>error</td>
    <td>update</td>
</tr>
<tr>
    <td>DELETE</td>
    <td>error</td>
    <td>update</td>
</tr>
</tbody>
</table>

Esta tabla describe el eje **método / URL**. Existe un segundo eje: el encabezado `Accept`.

Cuando `Accept` incluye `text/html`, el marco atiende a un navegador y aplica el patrón PRG, lo que introduce dos particularidades:

* El valor `_new` (configurable con `@entity_id_blank`) no es un identificador de entidad, sino el centinela que indica *sin entidad*. Por lo tanto `POST /{tipo}/_new` corresponde a la primera columna de la tabla y produce **create**.
* Un `POST` sobre un identificador real se trata como **update**, porque los formularios HTML estándar no pueden emitir `PATCH`.

En resumen:

| `Accept` | Método | `_entity_id` | Operación |
|---|---|---|---|
| `text/html` | POST | ausente o `_new` | create |
| `text/html` | POST | identificador real | update |
| cualquier otro | POST | ausente o presente | create |
| cualquiera | GET | ausente | list |
| cualquiera | GET | presente | read |
| cualquiera | GET | `_new` | formulario en blanco |
| cualquiera | PUT / PATCH | presente | update |
| cualquiera | DELETE | presente | delete |

El detalle completo está en [El controlador](crudl/controlador.md).

## Selección de vista

La vista se basa en el encabezado `Accept` y en el resultado de la operación.

Si `Accept` incluye `text/html`:

<table class="table">
<thead>
<tr>
    <th>Operación</th>
    <th>Éxito</th>
    <th>Fracaso</th>
</tr>
</thead>
<tbody>
<tr>
    <td>LIST</td>
    <td>list view</td>
    <td>error view</td>
</tr>
<tr>
    <td>READ</td>
    <td>form view</td>
    <td>error view</td>
</tr>
<tr>
    <td>CREATE</td>
    <td>redirect</td>
    <td>form view</td>
</tr>
<tr>
    <td>UPDATE</td>
    <td>redirect</td>
    <td>form view</td>
</tr>
<tr>
    <td>DELETE</td>
    <td>redirect</td>
    <td>error view</td>
</tr>
</tbody>
</table>

Si `Accept` **no** incluye `text/html`, la respuesta será JSON (`Content-Type: application/json`), tanto en éxito como en error.

Ver [Implementación de las vistas](crudl/vistas.md) y [Patrón PRG y redirección](crudl/prg-y-redireccion.md).

## Estructura de una entidad

Cada tipo de entidad tiene una carpeta con su nombre bajo la ruta indicada por `@base_path`.

Por ejemplo, para una entidad `cliente` con `@base_path="/misistema/entidades"`:

```
/misistema/entidades/cliente/form.dk
/misistema/entidades/cliente/list.dk
/misistema/entidades/cliente/model.dk
/misistema/entidades/cliente/controller.dk
```

Donde:

* `form.dk` es la vista específica de la entidad para presentación como formulario
* `list.dk` es la vista específica de las entidades presentadas como lista
* `model.dk` es un modelo específico para la entidad (opcional)
* `controller.dk` es un controlador específico para la entidad (opcional)

Ninguno de los cuatro es obligatorio. Si no existe `model.dk`, se usa el modelo genérico `entity.dk`; si no existen las vistas, se usan las genéricas incluidas en la carpeta `crudl`.

## Ejemplo mínimo

Una entidad `cliente` sobre una tabla del mismo nombre, sin código específico.

**`_protected/routes.map`**

```
/misistema/{_entities_type}/{_entity_id?} > misistema/entry-point.dkl
```

**`misistema/entry-point.dkl`**

```
#include "dkli.dkh"
#!

module "Controller configs"
{
    #include "functions.dkh"
    #include "serialize.dkh"
    #include "dbr.dkh"
    #include "crudl/crudl.dk"

    @path_root = "web/midominio.com"
    @base_path = "misistema/entidades"

    do crudl.load_config()
    do crudl.loadRoutesJSON()

    @dbmvc_path = "crudl/"
    @crudl.qname = "miconexion@misistema"

    #include "crudl/controller.dkl"
}
```

Con esto quedan disponibles:

```
GET    /misistema/cliente/          → lista
GET    /misistema/cliente/10        → lectura
GET    /misistema/cliente/_new      → formulario en blanco
POST   /misistema/cliente/          → alta
PATCH  /misistema/cliente/10        → modificación
DELETE /misistema/cliente/10        → baja
```

Para dar interfaz HTML basta agregar `misistema/entidades/cliente/form.dk` y `misistema/entidades/cliente/list.dk`.

## Documentos relacionados

* [El flujo de la solicitud HTTP](flujo-http.md) — enrutamiento, `routes.map`, `auth.dk`, `render.dk`
* [Devkron Basic Web Layer](bwl.md) — controlador de autorizaciones y proveedor de identidades
* [API webauth](webauth.md) — recuperación del token de sesión
* [IDP basado en la API Web de Induxsoft](idps.md) — proveedor de identidades predeterminado
* [Biblioteca dbr](../Bibliotecas-de-funciones/dbr/dbr.md) — patrón de diseño de tablas y funciones de acceso a datos
* [Ayudantes para generar HTML](uielements.md) — utilidades para construir vistas
