# Arquitectura de la aplicación

La aplicación sigue una arquitectura en capas donde cada responsabilidad tiene su lugar definido. El flujo de datos va desde la base de datos hacia la vista pasando por capas bien separadas.

---

## Flujo general

```
Vista (.php)
   ↑
Controlador (Controller)
   ↑
Business Object (BO)
   ↑
Service (Svc)
   ↑
DAO (Dao)
   ↑
Base de datos (SQL Server)
```

---

## Capas y sus clases

### 1. DAO — Acceso a datos (`Application/Dao/`)

Responsabilidad: conectarse a la BD, ejecutar queries y mapear filas a objetos.

#### Entity (`Dao/Entities/{Namespace}/{Tabla}.php`)
Representa la estructura de una tabla o vista. Sus propiedades se mapean directamente a columnas.

```php
#[Entity(Schema: 'Music')]
class VWAlbum {
    use VWAlbumT;

    public int     $IdAlbum    = 0;
    public string  $Titulo     = '';
    public int     $IndActivo  = 0;
    // ...
}
```

- El atributo `#[Entity(Schema: '...')]` le indica al ORM en qué schema buscar la tabla/vista.
- Campos con tipos especiales (ej: fechas) usan `#[EntityField(DataType: 'datetime')]`.
- **`*T.php`** es el trait de extensión manual (no se sobreescribe).

#### Dao (`Dao/Services/{Namespace}/{Tabla}Dao.php`)
Extiende `GenericDao`, que provee los métodos de acceso (`GetAll`, `GetBy`, `Insert`, `Update`, `Delete`, etc.).

```php
class VWAlbumDao extends GenericDao {
    use VWAlbumDaoT;

    function __construct($domain) {
        parent::__construct(VWAlbum::class, $domain);
    }
}
```

- **`*DaoT.php`** es el trait de extensión manual para queries personalizadas.

---

### 2. BLL — Lógica de negocio (`Application/BLL/`)

#### Dto (`BLL/DataTransferObjects/{Namespace}/{Tabla}Dto.php`)
Objeto de transferencia entre capas. Tiene las mismas propiedades que la Entity pero tipado para uso en PHP (constructor con named arguments).

```php
class VWAlbumDto {
    use VWAlbumDtoT;

    public function __construct(
        public int     $IdAlbum    = 0,
        public string  $Titulo     = '',
        public int     $IndActivo  = 0,
        // ...
    ) {}
}
```

- **`*DtoT.php`** es el trait de extensión manual. Es el lugar correcto para agregar propiedades calculadas o colecciones que el generador no puede inferir desde la BD:

```php
// VWAlbumDtoT.php — extensión manual, nunca se sobreescribe
trait VWAlbumDtoT {
    public array $Canciones = [];
}
```

#### Service (`BLL/Services/{Namespace}/{Tabla}Svc.php`)
Capa intermedia entre el BO y el DAO. Extiende `GenericSvc`, que provee métodos como `GetAll()`, `GetBy()`, `FirstWhere()`, `Insert()`, `Update()`, etc. Recibe el dominio de conexión como parámetro.

```php
class VWAlbumSvc extends GenericSvc {
    use VWAlbumSvcT;

    function __construct($domain) {
        parent::__construct(VWAlbumDto::class, VWAlbum::class, new VWAlbumDao($domain));
    }
}
```

- El Svc actúa como **mapper automático**: convierte Entity → Dto al leer y Dto → Entity al escribir.
- **`*SvcT.php`** es el trait de extensión manual. Contiene `$innerMappings` para mappings personalizados.

#### Business Object (`BLL/BusinessObjects/{Namespace}/{Nombre}BO.php`)
Orquesta la lógica de negocio. Instancia los Svc que necesita, combina datos de múltiples fuentes y devuelve objetos estructurados para el controlador.

```php
class MusicBO {
    public function ObtenerDatosHome() {
        $canciones = (new VWCancionSvc(ConnectionEnum::DEFAULT))->GetBy([
            new BindVariable('IndActivo', '=', 1)
        ]);

        $albumes = (new VWAlbumSvc(ConnectionEnum::DEFAULT))->GetBy([
            new BindVariable('IndActivo', '=', 1)
        ]);

        // combinar, filtrar, enriquecer...

        return (object)[
            'UltimosLanzamientos' => $albumes->Where('IndUltimosLanzamientos == 1'),
            'Albumes'             => $albumes,
        ];
    }
}
```

- Los BO **no** conocen la BD directamente; sólo hablan con Svc.
- Se organizan por dominio funcional, no por tabla (un BO puede usar múltiples Svc).

---

### 3. Controlador (`Application/Controllers/`)

Recibe la request HTTP, llama al BO y pasa los datos a la vista.

```php
#[Route(Path: '/home')]
class HomeController extends BaseController {

    #[Route(Path: '/')]
    #[ReturnViewResult]
    public function Index() {
        $data = (new MusicBO())->ObtenerDatosHome();
        return $this->RenderView('home', $data);
    }
}
```

- Las rutas se declaran con atributos PHP `#[Route(...)]`.
- `#[ReturnViewResult]` indica que el método retorna HTML (no JSON).
- `$data` queda disponible como variable implícita `$data` en la vista.

---

### 4. Vista (`Application/Views/`)

#### Layout (`Views/_Layouts/{nombre}Layout.php`)
Envuelve el contenido con el HTML base (head, fonts, CSS, scripts).

#### View principal (`Views/{Modulo}/{nombre}View.php`)
Declara el layout y delega cada sección a sub-vistas:

```php
@@Layout(guest)

<?php echo Display::GetRenderer('Core/Home/Sections')->RenderView('albumes', $data); ?>
```

#### Secciones (`Views/{Modulo}/{Nombre}/Sections/{seccion}View.php`)
Cada sección es un archivo PHP independiente con acceso a `$data`.

---

## Convención de nombres

| Capa | Archivo | Clase/Trait |
|---|---|---|
| Entity | `Dao/Entities/Music/VWAlbum.php` | `class VWAlbum` |
| Entity trait | `Dao/Entities/Music/VWAlbumT.php` | `trait VWAlbumT` |
| Dao | `Dao/Services/Music/VWAlbumDao.php` | `class VWAlbumDao` |
| Dao trait | `Dao/Services/Music/VWAlbumDaoT.php` | `trait VWAlbumDaoT` |
| Dto | `BLL/DataTransferObjects/Music/VWAlbumDto.php` | `class VWAlbumDto` |
| Dto trait | `BLL/DataTransferObjects/Music/VWAlbumDtoT.php` | `trait VWAlbumDtoT` |
| Service | `BLL/Services/Music/VWAlbumSvc.php` | `class VWAlbumSvc` |
| Service trait | `BLL/Services/Music/VWAlbumSvcT.php` | `trait VWAlbumSvcT` |
| Business Object | `BLL/BusinessObjects/Music/MusicBO.php` | `class MusicBO` |
| Controlador | `Controllers/Core/HomeController.php` | `class HomeController` |
| Vista | `Views/Core/Home/homeView.php` | — |
| Sección | `Views/Core/Home/Sections/albumesView.php` | — |

---

## Regla de los traits (`*T` / `*DtoT` / `*SvcT` / `*DaoT`)

Cada clase generada incluye un trait gemelo reservado para extensiones manuales:

- **El generador sobreescribe** `*Dao.php`, `*Entity.php`, `*Dto.php`, `*Svc.php`.
- **El generador nunca sobreescribe** los traits `*T.php`.

Por eso toda personalización — propiedades adicionales, métodos custom, mappings especiales — va siempre en el trait, nunca en la clase principal.

---

## ConnectionEnum

Las conexiones disponibles se centralizan en `Application/Configuration/ConnectionEnum.php`:

```php
class ConnectionEnum {
    public const DEFAULT = 'default';
}
```

Se usa como parámetro al instanciar cualquier Svc: `new VWAlbumSvc(ConnectionEnum::DEFAULT)`.
