diff --git a/app/Filament/Pages/GestionDashboard.php b/app/Filament/Pages/GestionDashboard.php index c51e9e9..c0c11d4 100644 --- a/app/Filament/Pages/GestionDashboard.php +++ b/app/Filament/Pages/GestionDashboard.php @@ -16,10 +16,8 @@ class GestionDashboard extends Page protected function getHeaderWidgets(): array { return [ - \App\Filament\Widgets\TelasStatsOverview::class, - // \App\Filament\Widgets\TelasStatsOverview::class, - // \App\Filament\Widgets\TelasEstadoOverview::class, - // \App\Filament\Widgets\TelasChart::class, + \App\Filament\Widgets\GestionKpisWidget::class, + \App\Filament\Widgets\AlertasStockBodegasWidget::class, ]; } diff --git a/app/Filament/Resources/OrdenProduccionResource.php b/app/Filament/Resources/OrdenProduccionResource.php index 71ae96f..b3c3f55 100644 --- a/app/Filament/Resources/OrdenProduccionResource.php +++ b/app/Filament/Resources/OrdenProduccionResource.php @@ -77,7 +77,8 @@ class OrdenProduccionResource extends Resource ->default(0), DatePicker::make('fecha_inicio') - ->required(), + ->required() + ->default(now()), DatePicker::make('fecha_entrega_estimada') ->required(), diff --git a/app/Filament/Widgets/GestionKpisWidget.php b/app/Filament/Widgets/GestionKpisWidget.php new file mode 100644 index 0000000..644079c --- /dev/null +++ b/app/Filament/Widgets/GestionKpisWidget.php @@ -0,0 +1,64 @@ +description('Total de órdenes de producción') + ->descriptionIcon('heroicon-m-clipboard-list') + ->color('primary'); + + $byState = OrdenProduccion::selectRaw('estado, count(*) as cnt')->groupBy('estado')->pluck('cnt', 'estado')->toArray(); + + $stats[] = Stat::make('En corte', $byState['en_corte'] ?? 0) + ->color('warning'); + $stats[] = Stat::make('En confección', $byState['en_confeccion'] ?? 0) + ->color('info'); + $stats[] = Stat::make('En tintorería', $byState['en_tintoreria'] ?? 0) + ->color('primary'); + $stats[] = Stat::make('En acabados', $byState['en_acabados'] ?? 0) + ->color('secondary'); + $stats[] = Stat::make('Finalizadas', $byState['finalizada'] ?? 0) + ->color('success'); + + $metros = Tela::sum('metros_disponibles'); + $stats[] = Stat::make('Metros disponibles', number_format($metros, 2) . ' m') + ->description('Total metros disponibles en stock') + ->descriptionIcon('heroicon-m-archive-box'); + + $atrasadas = OrdenProduccion::where('fecha_entrega_estimada', '<', now()->toDateString()) + ->where('estado', '!=', 'finalizada') + ->count(); + $stats[] = Stat::make('Órdenes atrasadas', $atrasadas) + ->color($atrasadas > 0 ? 'danger' : 'success') + ->description('OPs con fecha de entrega vencida'); + + return $stats; + } catch (\Exception $e) { + return [ + Stat::make('KPIs', 'Error') + ->description('Revisar logs') + ->color('danger'), + ]; + } + } + + protected function getColumns(): int + { + return 6; + } +} diff --git a/app/Models/OrdenProduccion.php b/app/Models/OrdenProduccion.php index bc099e2..9be5c0a 100644 --- a/app/Models/OrdenProduccion.php +++ b/app/Models/OrdenProduccion.php @@ -125,6 +125,11 @@ class OrdenProduccion extends Model $orden->numero_orden = 'OP-' . str_pad($ultimoId, 6, '0', STR_PAD_LEFT); } + + // Fecha de inicio por defecto hoy + if (! isset($orden->fecha_inicio) || ! $orden->fecha_inicio) { + $orden->fecha_inicio = now()->toDateString(); + } }); // Validar y reservar tela al cambiar de estado a 'en_corte' diff --git a/resources/views/filament/gestion-dashboard.blade.php b/resources/views/filament/gestion-dashboard.blade.php new file mode 100644 index 0000000..81b0307 --- /dev/null +++ b/resources/views/filament/gestion-dashboard.blade.php @@ -0,0 +1,87 @@ +@php +use App\Models\OrdenProduccion; +use App\Models\TrasladoPrenda; + +$kanbanStates = ['en_corte','en_confeccion','en_tintoreria','en_acabados','finalizada']; +$ordersByState = []; +foreach($kanbanStates as $s) { + $ordersByState[$s] = OrdenProduccion::where('estado', $s)->orderBy('fecha_entrega_estimada')->limit(6)->get(); +} + +$recentTrans = TrasladoPrenda::latest()->limit(8)->get(); +@endphp + +
+ {{-- Header filters (simple) --}} +
+

Dashboard de Gestión

+
+ Crear OP +
+
+ + {{-- KPIs are rendered by widgets above --}} + +
+ {{-- Kanban column (span 2) --}} +
+

Pipeline de Órdenes

+
+ @foreach($ordersByState as $state => $orders) +
+

{{ ucfirst(str_replace('_',' ', $state)) }} ({{ $orders->count() }})

+ +
+ @endforeach +
+
+ + {{-- Timeline of shipments --}} +
+

Últimos envíos (traslados)

+
    + @foreach($recentTrans as $t) +
  • +
    +
    Traslado #{{ $t->id }} — OP #{{ $t->orden_produccion_id }}
    +
    {{ ucfirst($t->origen) }} → {{ ucfirst($t->destino) }} · Cant: {{ $t->cantidad_enviada }} · Estado: {{ ucfirst($t->estado) }}
    +
    +
    + Ver + @if($t->estado !== 'recibido') +
    + @csrf + +
    + @endif +
    +
  • + @endforeach +
+
+
+ + {{-- Activity & Alerts row --}} +
+
+

Actividad reciente

+

Aquí verás eventos relevantes: creaciones, traslados, inventarios, etc.

+ {{-- Placeholder: implement live feed --}} +
+
+

Alertas

+

Telas con stock bajo, órdenes atrasadas.

+ {{-- The Alerts widget will be shown in header; this is a placeholder for further details --}} +
+
+ +
\ No newline at end of file