# Guía para el Desarrollador - GCE

Esta guía explica brevemente los directorios y archivos más importantes del proyecto, y qué sucede cuando se modifican.

---

## MODELS (app\Models)

Dentro de este directorio encontrarás los modelos Eloquent. **Sí, cada modelo corresponde a una tabla en la base de datos**, pero hay dos tipos importantes:

### Modelos Principales (Entidades del Negocio)

Estos representan las entidades principales del sistema y cada uno corresponde a una tabla principal:

- **User.php** → tabla `users` (usuarios del sistema)
- **Alumno.php** → tabla `alumnos` (estudiantes)
- **Docente.php** → tabla `docentes` (profesores)
- **Adscripto.php** → tabla `adscriptos` (personal de apoyo)
- **Padre.php** → tabla `padres` (padres/tutores)
- **Colegio.php** → tabla `colegios` (instituciones educativas)
- **Ciclo.php** → tabla `ciclos` (años/ciclos lectivos)
- **Turno.php** → tabla `turnos` (horarios: mañana, tarde, etc.)
- **Asignatura.php** → tabla `asignaturas` (materias)
- **Grupo.php** → tabla `grupos` (grupos/clases)
- **Calificacion.php** → tabla `calificacions` (notas/evaluaciones)
- **Rol.php** → tabla `roles` (roles de usuario)

**¿Qué pasa si modifico uno de estos modelos?**

Cada modelo tiene varias propiedades importantes que puedes modificar. Aquí te muestro dónde encontrarlas:

#### 1. `$fillable` (Campos asignables masivamente)

**¿Dónde está?** Al inicio de la clase, después de `use AsSource, Filterable;`

**Ejemplo en `Docente.php` (líneas 15-19):**
```php
protected $fillable = [
    'user_id',
    'fecha_ingreso',
    'observaciones',
];
```

**¿Qué pasa si lo modifico?**
- Define qué campos se pueden asignar masivamente (usando `create()` o `update()`).
- Si agregas/quitas campos aquí, deberás actualizar los **Layouts** correspondientes para incluir/excluir esos campos en los formularios.
- Si intentas guardar un campo que NO está en `$fillable`, Laravel lo ignorará por seguridad.

#### 2. `$casts` (Conversión de tipos de datos)

**¿Dónde está?** Justo después de `$fillable`

**Ejemplo en `Docente.php` (líneas 21-23):**
```php
protected $casts = [
    'fecha_ingreso' => 'date',
];
```

**Ejemplo en `User.php` (líneas 49-54):**
```php
protected $casts = [
    'permissions'          => 'array',
    'email_verified_at'    => 'datetime',
    'fecha_nacimiento'     => 'date',
    'activo'               => 'boolean',
];
```

**¿Qué pasa si lo modifico?**
- Define cómo Laravel convierte los datos de la base de datos a tipos PHP.
- Si cambias `'activo' => 'boolean'`, el campo se convertirá automáticamente a true/false.
- Los **Layouts** y **Screens** que trabajen con esos campos verán el cambio de tipo de dato.

#### 3. `$allowedFilters` y `$allowedSorts` (Filtros y ordenamiento)

**¿Dónde está?** Solo algunos modelos los tienen (como `User.php`)

**Ejemplo en `User.php` (líneas 61-67 y 74-80):**
```php
protected $allowedFilters = [
    'id'         => Where::class,
    'name'       => Like::class,
    'email'      => Like::class,
    'updated_at' => WhereDateStartEnd::class,
    'created_at' => WhereDateStartEnd::class,
];

protected $allowedSorts = [
    'id',
    'name',
    'email',
    'updated_at',
    'created_at',
];
```

**¿Qué pasa si lo modifico?**
- Afecta las capacidades de filtrado y ordenamiento en las pantallas de listado (**ListScreen**).
- Si agregas un campo aquí, los usuarios podrán filtrar/ordenar por ese campo en las listas.
- **Nota**: No todos los modelos tienen estas propiedades. Solo los que usan `Filterable` y se muestran en listas.

#### 4. Relaciones (`hasOne`, `belongsToMany`, etc.)

**¿Dónde están?** Son métodos públicos dentro de la clase

**Ejemplo en `Docente.php` (líneas 28-60):**
```php
public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

public function asignaturas(): BelongsToMany
{
    return $this->belongsToMany(Asignatura::class, 'docente_asignatura_grupos', ...);
}
```

**¿Qué pasa si lo modifico?**
- Afecta cómo se cargan datos relacionados.
- Los **Screens** que usen estas relaciones verán reflejados los cambios automáticamente.
- Por ejemplo, si cambias `user()` en `Docente`, afecta cómo se carga el usuario relacionado cuando trabajas con un docente.

### Modelos de Tablas Intermedias (Tablas Pivot)

Estos modelos representan tablas intermedias que conectan dos o más entidades principales. Se usan para relaciones "muchos a muchos":

- **AlumnoGrupo.php** → tabla `alumno_grupos` (relaciona alumnos con grupos)
- **PadreAlumno.php** → tabla `padre_alumnos` (relaciona padres con alumnos)
- **AdscriptoDocente.php** → tabla `adscripto_docentes` (relaciona adscriptos con docentes)
- **AdscriptoGrupo.php** → tabla `adscripto_grupos` (relaciona adscriptos con grupos)
- **DocenteAsignaturaGrupo.php** → tabla `docente_asignatura_grupos` (relaciona docentes, asignaturas y grupos)
- **ColegioCiclo.php** → tabla `colegio_ciclos` (relaciona colegios con ciclos)

**¿Qué pasa si modifico uno de estos modelos?**
- Generalmente **NO necesitas modificar estos modelos** a menos que:
  - Agregues campos adicionales a la tabla intermedia (además de las claves foráneas)
  - Necesites lógica especial para manejar estas relaciones
- Si modificas estos modelos, afecta cómo se manejan las relaciones en los modelos principales. Por ejemplo, si cambias `AlumnoGrupo`, afecta cómo `Alumno` se relaciona con `Grupo`.
- **Normalmente no tienen Layouts ni Screens propios** - se manejan a través de los modelos principales.

---

## LAYOUTS (app\Orchid\Layouts)

Dentro de este directorio encontrarás los componentes visuales que definen la estructura de formularios y listas. Cada entidad suele tener:
- `*EditLayout.php`: Define los campos del formulario de edición/creación
- `*ListLayout.php`: Define las columnas que se muestran en las listas

**¿Qué pasa si modifico un archivo aquí?**
- **Cambios en campos de formulario** (`EditLayout`): Se reflejan inmediatamente en las pantallas de creación/edición (**EditScreen**). Si agregas un campo nuevo, asegúrate de que:
  - El campo exista en la base de datos (migration) o esté en el `$fillable` del **Model** correspondiente
  - El **Screen** maneje la validación y guardado de ese campo
- **Cambios en columnas de lista** (`ListLayout`): Se reflejan inmediatamente en las pantallas de listado (**ListScreen**). Si agregas una columna nueva, asegúrate de que el dato exista en el query del **Screen**.
- **Cambios en validaciones** (required, max, etc.): Afectan la validación del formulario. Los mensajes de error se mostrarán en la interfaz.

---

## SCREENS (app\Orchid\Screens)

Dentro de este directorio encontrarás las pantallas que manejan la lógica de negocio y las interacciones del usuario. Cada entidad suele tener:
- `*EditScreen.php`: Maneja la creación y edición de registros
- `*ListScreen.php`: Maneja el listado y filtrado de registros

**¿Qué pasa si modifico un archivo aquí?**
- **Cambios en el método `query()`**: Afecta qué datos se cargan y se pasan a los **Layouts**. Si agregas/quitas datos aquí, deberás actualizar los **Layouts** correspondientes.
- **Cambios en el método `save()` o `create()`**: Afecta cómo se guardan los datos en la base de datos. Debes asegurarte de que los campos que intentas guardar existan en el `$fillable` del **Model**.
- **Cambios en validaciones**: Afectan qué datos se aceptan antes de guardar. Los errores se mostrarán al usuario.
- **Cambios en acciones** (botones, enlaces): Se reflejan inmediatamente en la interfaz.
- **Cambios en el método `layout()`**: Afecta qué **Layouts** se muestran en la pantalla. Si cambias el layout, la estructura visual cambiará.

---

## GESTIÓN DE PERMISOS POR ROL

El sistema permite implementar restricciones de acceso basadas en roles de usuario. Por ejemplo, los docentes solo pueden ver y gestionar sus propios grupos y calificaciones, mientras que los administradores tienen acceso completo.

### Identificar el Rol del Usuario Autenticado

Para verificar si un usuario tiene un rol específico, usa la relación entre `User` y los modelos de rol (Docente, Alumno, Padre, Adscripto):

```php
use Illuminate\Support\Facades\Auth;

$user = Auth::user();

// Verificar si el usuario es docente
if ($user && $user->docente) {
    $docente = $user->docente;
    // Acceder al ID del docente: $docente->id
}

// Verificar si el usuario es alumno
if ($user && $user->alumno) {
    $alumno = $user->alumno;
}

// Verificar si el usuario es padre
if ($user && $user->padre) {
    $padre = $user->padre;
}
```

### Paso 1: Filtrar Datos en ListScreen

En el método `query()` del **ListScreen**, agrega lógica condicional para filtrar los datos según el rol:

**Ejemplo en `GrupoListScreen.php`:**

```php
use Illuminate\Support\Facades\Auth;

public function query(): iterable
{
    $user = Auth::user();
    $query = Grupo::with(['colegioCiclo.colegio', 'colegioCiclo.ciclo', 'turno']);
    
    // Si el usuario autenticado es un docente, filtrar solo sus grupos
    if ($user && $user->docente) {
        $docente = $user->docente;
        // Obtener los IDs de los grupos asignados al docente
        $gruposIds = $docente->grupos()
            ->select('grupos.id')
            ->distinct()
            ->pluck('grupos.id')
            ->toArray();
        
        // Filtrar solo los grupos del docente
        if (!empty($gruposIds)) {
            $query->whereIn('grupos.id', $gruposIds);
        } else {
            // Si el docente no tiene grupos asignados, no mostrar ninguno
            $query->whereRaw('1 = 0');
        }
    }
    
    return ['grupos' => $query->defaultSort('id', 'desc')->paginate()];
}
```

**Ejemplo en `CalificacionAlumnoScreen.php`:**

```php
public function query(Alumno $alumno, Request $request): iterable
{
    // Construir query de calificaciones
    $calificacionesQuery = Calificacion::with(['alumno.user', 'asignatura', 'docente.user'])
        ->where('alumno_id', $alumno->id);
    
    // Si el usuario autenticado es un docente, filtrar solo sus calificaciones
    $user = Auth::user();
    if ($user && $user->docente) {
        $calificacionesQuery->where('docente_id', $user->docente->id);
    }
    
    return [
        'calificaciones' => $calificacionesQuery
            ->orderBy('anio', 'desc')
            ->orderBy('mes', 'desc')
            ->paginate(),
    ];
}
```

### Paso 2: Ocultar Botones en CommandBar

En el método `commandBar()` del **Screen**, condiciona la aparición de botones según el rol:

**Ejemplo en `GrupoListScreen.php`:**

```php
public function commandBar(): iterable
{
    $user = Auth::user();
    $commandBar = [];
    
    // Solo mostrar el botón "Agregar" si el usuario NO es un docente
    if (!$user || !$user->docente) {
        $commandBar[] = Link::make(__('Agregar'))
            ->icon('bs.plus-circle')
            ->route('platform.systems.grupos.create');
    }
    
    return $commandBar;
}
```

### Paso 3: Ocultar Acciones en ListLayout

En el método `columns()` del **ListLayout**, condiciona las acciones (editar, eliminar) según el rol:

**Ejemplo en `GrupoListLayout.php`:**

```php
use Illuminate\Support\Facades\Auth;

public function columns(): array
{
    $user = Auth::user();
    $isDocente = $user && $user->docente;
    
    return [
        // ... otras columnas ...
        TD::make(__('Acciones'))
            ->align(TD::ALIGN_CENTER)
            ->width('100px')
            ->render(function (Grupo $grupo) use ($isDocente) {
                $actions = [
                    Link::make(__('Ver Alumnos'))
                        ->route('platform.systems.grupos.alumnos', $grupo->id)
                        ->icon('bs.people'),
                ];
                
                // Solo mostrar acciones de editar y eliminar si NO es docente
                if (!$isDocente) {
                    $actions[] = Link::make(__('Editar'))
                        ->route('platform.systems.grupos.edit', $grupo->id)
                        ->icon('bs.pencil');
                    $actions[] = Button::make(__('Eliminar'))
                        ->icon('bs.trash3')
                        ->confirm(__('¿Está seguro?'))
                        ->method('remove', ['id' => $grupo->id]);
                }
                
                return DropDown::make()
                    ->icon('bs.three-dots-vertical')
                    ->list($actions);
            }),
    ];
}
```

**Ejemplo más específico en `CalificacionAlumnoLayout.php` (verificar propiedad del registro):**

```php
public function columns(): array
{
    return [
        // ... otras columnas ...
        TD::make(__('Acciones'))
            ->render(function (Calificacion $cal) {
                $user = Auth::user();
                $isDocente = $user && $user->docente;
                $esMiCalificacion = $isDocente && $cal->docente_id == $user->docente->id;
                
                // Si es docente y la calificación no es suya, no mostrar acciones
                if ($isDocente && !$esMiCalificacion) {
                    return '-';
                }
                
                // Mostrar acciones de editar y eliminar
                return DropDown::make()
                    ->icon('bs.three-dots-vertical')
                    ->list([
                        Link::make(__('Editar'))->route(...)->icon('bs.pencil'),
                        Button::make(__('Eliminar'))->icon('bs.trash3')->method('remove', $params),
                    ]);
            }),
    ];
}
```

### Paso 4: Validación de Seguridad en Métodos de Eliminación/Edición

Agrega validaciones adicionales en los métodos `remove()`, `save()`, etc., para prevenir accesos no autorizados:

**Ejemplo en `CalificacionAlumnoScreen.php`:**

```php
public function remove(Request $request)
{
    $user = Auth::user();
    
    // Si el usuario es docente, verificar que la calificación sea suya
    if ($user && $user->docente) {
        $docenteIdRequest = $request->get('docente_id');
        if ($docenteIdRequest != $user->docente->id) {
            Toast::error(__('No tiene permiso para eliminar esta calificación'));
            return redirect()->back();
        }
    }
    
    // Proceder con la eliminación
    $query = Calificacion::where(...)->delete();
    Toast::info(__('Calificación eliminada correctamente'));
    return redirect()->back();
}
```

### Resumen de Pasos para Implementar Restricciones por Rol

1. **Identificar el rol**: Usa `Auth::user()` y verifica la relación (ej: `$user->docente`)
2. **Filtrar en `query()`**: Agrega condiciones `where()` según el rol en el método `query()` del **ListScreen**
3. **Ocultar botones en `commandBar()`**: Condiciona la aparición de botones según el rol
4. **Ocultar acciones en `ListLayout`**: Condiciona las acciones en las columnas según el rol y/o propiedad del registro
5. **Validar en métodos de acción**: Agrega validaciones de seguridad en `remove()`, `save()`, etc.

### Notas Importantes

- **Siempre valida en el servidor**: No confíes solo en ocultar elementos en la interfaz. Agrega validaciones en los métodos del **Screen**.
- **Los administradores deben ver todo**: Asegúrate de que los usuarios sin rol específico (administradores) puedan acceder a todos los datos.
- **Usa relaciones del modelo**: Aprovecha las relaciones definidas en los modelos (ej: `$docente->grupos()`) para filtrar datos relacionados.

---

## ROUTES (routes\platform.php)

Este archivo registra todas las rutas del panel administrativo (Orchid Platform).

**¿Qué pasa si modifico este archivo?**
- **Agregar/quitar rutas**: Afecta qué URLs están disponibles. Si agregas una ruta nueva, deberás crear el **Screen** correspondiente y posiblemente agregar un ítem al menú en **PlatformProvider**.
- **Cambiar nombres de rutas**: Afecta todas las referencias a esa ruta en el código (menús, enlaces, redirecciones). Deberás actualizar **PlatformProvider** y cualquier **Screen** que use esa ruta.

---

## PLATFORMPROVIDER (app\Orchid\PlatformProvider.php)

Este archivo configura el menú lateral y los permisos del sistema.

**¿Qué pasa si modifico este archivo?**
- **Cambios en `menu()`**: Afectan directamente el menú lateral de la aplicación. Si agregas/quitas ítems del menú, se reflejan inmediatamente en la interfaz. Asegúrate de que la ruta exista en **routes\platform.php**.
- **Cambios en `permissions()`**: Afectan qué permisos están disponibles en el sistema. Los roles pueden tener estos permisos asignados, y los ítems del menú pueden requerirlos para mostrarse.

---

## MIGRATIONS (database\migrations)

Estos archivos definen la estructura de las tablas de la base de datos.

**¿Qué pasa si modifico o creo un archivo aquí?**
- **Agregar columnas nuevas**: Después de ejecutar la migración, deberás:
  - Agregar el campo al `$fillable` del **Model** correspondiente
  - Agregar el campo al **EditLayout** si quieres que sea editable
  - Actualizar el **Screen** si necesitas lógica especial para ese campo
- **Modificar columnas existentes**: Puede afectar la validación en **Layouts** y **Screens**. Revisa que los tipos de datos coincidan.
- **Crear tablas nuevas**: Deberás crear el **Model**, **Layouts** (Edit y List), **Screens** (Edit y List), y registrar las rutas en **routes\platform.php**.

---

## FILTERS (app\Orchid\Filters)

Dentro de este directorio encontrarás filtros personalizados para las listas.

**¿Qué pasa si modifico un archivo aquí?**
- Los cambios se reflejan en las pantallas de listado (**ListScreen**) que usen ese filtro. Afecta cómo los usuarios pueden filtrar los datos en las tablas.

---

## PRESENTERS (app\Orchid\Presenters)

Dentro de este directorio encontrarás clases que transforman datos para mostrarlos de forma personalizada.

**¿Qué pasa si modifico un archivo aquí?**
- Los cambios afectan cómo se muestran los datos en los **Layouts** y **Screens** que usen ese presenter. Útil para formatear fechas, nombres, etc.

---

## FLUJO DE DATOS TÍPICO

1. **Usuario accede a una URL** → `routes\platform.php` determina qué **Screen** cargar
2. **Screen se ejecuta** → El método `query()` carga datos del **Model**
3. **Screen pasa datos a Layouts** → Los **Layouts** definen cómo mostrar esos datos
4. **Usuario envía formulario** → El **Screen** valida y guarda usando el **Model**
5. **Model guarda en BD** → La estructura de la BD está definida por las **Migrations**

---

## CONSEJOS PARA MANTENIMIENTO

- **Al agregar un campo nuevo**: Actualiza Migration → Model (`$fillable`) → EditLayout → Screen (validación y guardado)
- **Al modificar una relación**: Actualiza Model → Revisa Screens que usen esa relación → Actualiza Layouts si es necesario
- **Al cambiar una ruta**: Actualiza `routes\platform.php` → Actualiza `PlatformProvider.php` (menú) → Busca referencias en Screens
- **Al agregar una nueva entidad**: Crea Migration → Model → EditLayout y ListLayout → EditScreen y ListScreen → Rutas en `platform.php` → Menú en `PlatformProvider.php`

---

## ARCHIVOS DE CONFIGURACIÓN IMPORTANTES

- **config\platform.php**: Configuración general de Orchid Platform
- **config\database.php**: Configuración de la base de datos
- **.env**: Variables de entorno (conexión BD, etc.)

