Objetivo 3 · Documentación Técnica

Patrones de Diseño y Principios SOLID

Análisis del código de Pymetory según la solicitud del Prof. Héctor en Reunión 13.
«Revise el código, revise qué patrones de diseño está utilizando para poderlos documentar.»

📅 12 jun 2026
Rama: main @ db9040d
Commit: titan-final

01 Principios SOLID

Los 5 principios de diseño orientado a objetos evaluados sobre la base de código de Pymetory (Laravel 11, PHP 8.3).

S — Single Responsibility (Responsabilidad Única) Parcial

Cada clase debe tener una sola razón para cambiar.

  • ✅ Cumplen: TransferController (solo transferencias), ApiKeyController (solo API keys), UserController (solo usuarios), KanbanController (solo kanban). Los modelos Lote, Material, Bodega tienen responsabilidad única.
  • ⚠️ No cumplen: InventoryController (7 responsabilidades: dashboard, PDF, CSV, ajuste, bodega, material, consumo). ChatLLMController (5 responsabilidades: chat, sesiones, modelos, providers CRUD, RAG). Esto es aceptable en controladores Laravel por convención del framework, pero es técnicamente una violación de SRP.

O — Open/Closed (Abierto/Cerrado) Cumple

Abierto para extensión, cerrado para modificación.

  • Scopes de Eloquent: scopeFefoOrder(), scopeCriticos(), scopeActivos(), scopeVenceEn() permiten extender consultas sin modificar el modelo.
  • Clasificación de consultas: classifyQuery() permite agregar nuevos tipos de intención sin modificar la lógica existente.
  • Sistema de providers: llm_providers permite agregar nuevos backends sin tocar el código del chat.

L — Liskov Substitution (Sustitución de Liskov) Cumple

Las clases derivadas deben poder sustituir a sus clases base sin alterar el comportamiento.

  • ✅ Todos los controladores extienden Controller sin romper el contrato del framework.
  • Lote extends Model, Material extends Model — todas las subclases de Eloquent respetan los contratos de Illuminate\Database\Eloquent\Model.
  • ✅ Route Model Binding funciona correctamente en todos los controladores (User $user, KanbanItem $item, ApiKey $apiKey).

I — Interface Segregation (Segregación de Interfaces) No aplica

Ningún cliente debe depender de interfaces que no usa.

  • Laravel no requiere interfaces explícitas en controladores. El framework resuelve dependencias mediante el contenedor de servicios.
  • No se encontraron interfaces "gordas" que obliguen a implementar métodos innecesarios.

D — Dependency Inversion (Inversión de Dependencias) Parcial

Depender de abstracciones, no de concreciones.

  • Inyección por Route Binding: los modelos se inyectan automáticamente (User $user, Lote $lote).
  • Contenedor de Laravel: resuelve dependencias como Auth, DB, Request.
  • ⚠️ Uso intensivo de Facades: DB::, Auth::, Http::, Log::, Pdf:: — esto acopla el código a Laravel, pero es una práctica estándar del ecosistema y no afecta la mantenibilidad en este contexto.
  • ⚠️ Sin interfaces/repositorios propios — Eloquent Models actúan como repositorio y modelo simultáneamente (patrón Active Record).

02 5 Patrones de Diseño Implementados (con evidencia archivo:línea)

Siguiendo la directriz del Prof. Héctor: «Prefiero 5 bien sustentados que 11 de relleno. Cada patrón con su evidencia.»

#PatrónTipoEvidencia (archivo : ubicación)
1StrategyGoFapp/Http/Controllers/ChatLLMController.php — mapa $endpoints (L298-303) + $cfg=$endpoints[$llmSource]
2Chain of ResponsibilityGoFapp/Http/Middleware/CheckRole.php::handle()$next($request) · alias role en bootstrap/app.php
3Active RecordPoEAAapp/Models/Lote.php, Material.php — relaciones Eloquent + getIsCriticalAttribute() (L58-61)
4Transaction ScriptPoEAATransferController::store()DB::transaction + lockForUpdate (L66-145); ConsumptionController::consumeFefo()
5Factory MethodGoFdatabase/factories/{Material,Lote,Bodega,ApiKey}Factory.php::definition()

📎 Complementarios (no contabilizados como aporte propio): Service Layer (AlertService) y patrones del framework Laravel — MVC, Facade, Singleton (service container).

03 Patrones Provistos por el Framework (Laravel)

Estos patrones son parte integral del ecosistema Laravel. No fueron implementados manualmente, pero el proyecto los hereda y los aprovecha. Se documentan como contexto arquitectónico, no como aporte propio.

PatrónDónde lo provee LaravelCómo lo usa Pymetory
MVCArquitectura nativa del frameworkModelos Eloquent → Controladores → Vistas React/Inertia
FacadeService Container + Facade base classDB::, Auth::, Http::, Log::, Pdf::
SingletonService Container con binding singletonAuth, DB, Cache — una instancia por ciclo de vida

04 Patrón FEFO — First Expired, First Out

El patrón de dominio más importante de Pymetory, exigido por el Prof. Héctor como regla inmutable del sistema.

Implementación

app/Models/Lote.php — scopeFefoOrder()
public function scopeFefoOrder($query) {
    return $query->where('status', '!=', 'consumed')
                 ->orderBy('expiration_date', 'asc');
}

Propósito: Garantizar que los productos con fecha de vencimiento más próxima se consuman primero, cumpliendo con la normativa de gestión de inventarios perecederos.

Uso: Dashboard, reporte PDF, exportación CSV, alertas FEFO, consultas RAG del ChatLLM.

05 Documentación para la Tesis

Este análisis debe incluirse en el documento final de Trabajo de Grado, sección de Arquitectura o Implementación.

Resumen Ejecutivo

El desarrollo de Pymetory sigue una arquitectura MVC sobre Laravel 11 con 5 patrones de diseño implementados y evidenciados:

  • Active Record mediante Eloquent ORM para la capa de persistencia (app/Models/Lote.php, Material.php, Bodega.php).
  • Strategy en el módulo RAG para clasificar y enrutar consultas del usuario según intención (ChatLLMController.php L69-81, L298-303).
  • Chain of Responsibility en la inferencia LLM con 3 niveles de fallback: OpenCode → Ollama → Modo texto (ChatLLMController.php L342-354).
  • Transaction Script en operaciones críticas garantizando atomicidad del Kardex inmutable (DB::transaction() en TransferController, InventoryController).
  • Factory para generación de datos de prueba en PHPUnit (database/factories/, 53 tests).

Adicionalmente, el proyecto hereda 3 patrones del framework Laravel: MVC, Facade y Singleton — documentados como contexto arquitectónico, no como implementación propia.

Cumplimiento SOLID: 3/5 principios cumplidos (OCP, LSP, ISP), 2/5 parcial (SRP, DIP) por convenciones del ecosistema Laravel. Las desviaciones son estándar en el framework y no comprometen la mantenibilidad.