schema([]); } public static function table(Table $table): Table { return $table ->query( OrdenProduccion::query() ->orderBy('created_at', 'desc') ) ->columns([ Tables\Columns\TextColumn::make('numero_orden') ->label('Orden') ->searchable() ->sortable(), Tables\Columns\TextColumn::make('prenda_modelo') ->label('Prenda') ->searchable() ->limit(30), Tables\Columns\TextColumn::make('referencia') ->label('Referencia') ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('cantidad_total') ->label('Total') ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('estado') ->badge() ->colors([ 'danger' => 'cancelada', 'warning' => fn ($state) => in_array($state, ['pendiente', 'en_confeccion', 'en_tintoreria', 'en_acabados']), 'success' => 'finalizada', 'primary' => 'en_proceso', ]), Tables\Columns\TextColumn::make('confeccion') ->label('📦 Confección') ->alignCenter() ->state(function (OrdenProduccion $record): string { $enviadas = $record->confecciones()->sum('cantidad_enviada'); $recibidas = $record->confecciones()->sum('cantidad_recibida'); // Calcular disponibles (recibidas - arreglos - cobros - enviadas a ojales) $arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($record) { $q->where('orden_produccion_id', $record->id); })->where('tipo', 'arreglo')->sum('cantidad'); $cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($record) { $q->where('orden_produccion_id', $record->id); })->sum('cantidad'); $disponiblesConfeccion = $recibidas - $arreglos - $cobros; $enviadasOjales = $record->ojales()->sum('cantidad_enviada'); $pendientes = max(0, $disponiblesConfeccion - $enviadasOjales); return "E:{$enviadas} R:{$recibidas} P:{$pendientes}"; }) ->color(fn (OrdenProduccion $record) => self::getPendienteConfeccion($record) > 0 ? 'warning' : 'gray') ->tooltip('E=Enviadas, R=Recibidas, P=Pendientes'), Tables\Columns\TextColumn::make('ojales') ->label('🔘 Ojales') ->alignCenter() ->state(function (OrdenProduccion $record): string { $enviadas = $record->ojales()->sum('cantidad_enviada'); $terminadas = $record->ojales()->where('terminada', true)->sum('cantidad_enviada'); $pendientes = max(0, $enviadas - $terminadas); return "E:{$enviadas} T:{$terminadas} P:{$pendientes}"; }) ->color(fn (OrdenProduccion $record) => self::getPendienteOjales($record) > 0 ? 'warning' : 'gray') ->tooltip('E=Enviadas, T=Terminadas, P=Pendientes'), Tables\Columns\TextColumn::make('presillas') ->label('⚫ Presillas') ->alignCenter() ->state(function (OrdenProduccion $record): string { $enviadas = $record->prensillas()->sum('cantidad_enviada'); $terminadas = $record->prensillas()->where('terminada', true)->sum('cantidad_enviada'); $pendientes = max(0, $enviadas - $terminadas); return "E:{$enviadas} T:{$terminadas} P:{$pendientes}"; }) ->color(fn (OrdenProduccion $record) => self::getPendientePresillas($record) > 0 ? 'warning' : 'gray') ->tooltip('E=Enviadas, T=Terminadas, P=Pendientes'), Tables\Columns\TextColumn::make('tintoreria') ->label('🎨 Tintorería') ->alignCenter() ->state(function (OrdenProduccion $record): string { $enviadas = $record->tintorerias()->sum('cantidad_enviada'); $recepciones = 0; foreach ($record->tintorerias as $tintoreria) { $recepciones += (int) $tintoreria->recepciones() ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); } $pendientes = max(0, $enviadas - $recepciones); return "E:{$enviadas} R:{$recepciones} P:{$pendientes}"; }) ->color(fn (OrdenProduccion $record) => self::getPendienteTintoreria($record) > 0 ? 'warning' : 'gray') ->tooltip('E=Enviadas, R=Recibidas, P=Pendientes'), Tables\Columns\TextColumn::make('acabados') ->label('✨ Acabados') ->alignCenter() ->state(function (OrdenProduccion $record): string { // Disponibles desde tintorería $disponibles = 0; foreach ($record->tintorerias as $tintoreria) { $recep = (int) $tintoreria->recepciones() ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $reprocesos = (int) $tintoreria->ajustes() ->where('tipo', 'reproceso')->sum('cantidad'); $cobros = (int) $tintoreria->cobros()->sum('cantidad'); $disponibles += ($recep - $reprocesos - $cobros); } $enviadasAcabados = $record->procesosAcabado()->sum('cantidad_enviada'); $recibidasAcabados = $record->procesosAcabado() ->whereNotNull('fecha_recepcion') ->sum('cantidad_recibida'); $pendientes = max(0, $disponibles - $enviadasAcabados); return "D:{$disponibles} E:{$enviadasAcabados} P:{$pendientes}"; }) ->color(fn (OrdenProduccion $record) => self::getPendienteAcabados($record) > 0 ? 'warning' : 'gray') ->tooltip('D=Disponibles, E=Enviadas, P=Pendientes'), Tables\Columns\TextColumn::make('bodega') ->label('📦 Bodega') ->alignCenter() ->state(function (OrdenProduccion $record): string { $total = $record->inventarioPrenda()->sum('cantidad_terminada'); $disponible = $record->inventarioPrenda()->sum('cantidad_disponible'); return "T:{$total} D:{$disponible}"; }) ->color(fn (OrdenProduccion $record) => self::getEnBodega($record) > 0 ? 'success' : 'gray') ->tooltip('T=Total, D=Disponible'), ]) ->filters([ Tables\Filters\SelectFilter::make('estado') ->options([ 'pendiente' => 'Pendiente', 'en_proceso' => 'En Proceso', 'en_confeccion' => 'En Confección', 'en_tintoreria' => 'En Tintorería', 'en_acabados' => 'En Acabados', 'finalizada' => 'Finalizada', 'cancelada' => 'Cancelada', ]), Tables\Filters\Filter::make('con_pendientes') ->label('Solo con pendientes') ->query(fn (Builder $query) => $query->whereIn('estado', ['en_proceso', 'en_confeccion', 'en_tintoreria', 'en_acabados'])), ]) ->actions([]) ->bulkActions([]) ->defaultSort('created_at', 'desc') ->paginated([10, 25, 50, 100]) ->poll('30s'); } protected static function getPendienteConfeccion(OrdenProduccion $record): int { $recibidas = $record->confecciones()->sum('cantidad_recibida'); $arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($record) { $q->where('orden_produccion_id', $record->id); })->where('tipo', 'arreglo')->sum('cantidad'); $cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($record) { $q->where('orden_produccion_id', $record->id); })->sum('cantidad'); $disponiblesConfeccion = $recibidas - $arreglos - $cobros; $enviadasOjales = $record->ojales()->sum('cantidad_enviada'); return max(0, $disponiblesConfeccion - $enviadasOjales); } protected static function getPendienteOjales(OrdenProduccion $record): int { $enviadas = $record->ojales()->sum('cantidad_enviada'); $terminadas = $record->ojales()->where('terminada', true)->sum('cantidad_enviada'); return max(0, $enviadas - $terminadas); } protected static function getPendientePresillas(OrdenProduccion $record): int { $enviadas = $record->prensillas()->sum('cantidad_enviada'); $terminadas = $record->prensillas()->where('terminada', true)->sum('cantidad_enviada'); return max(0, $enviadas - $terminadas); } protected static function getPendienteTintoreria(OrdenProduccion $record): int { $enviadas = $record->tintorerias()->sum('cantidad_enviada'); $recepciones = 0; foreach ($record->tintorerias as $tintoreria) { $recepciones += (int) $tintoreria->recepciones() ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); } return max(0, $enviadas - $recepciones); } protected static function getPendienteAcabados(OrdenProduccion $record): int { $disponibles = 0; foreach ($record->tintorerias as $tintoreria) { $recep = (int) $tintoreria->recepciones() ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $reprocesos = (int) $tintoreria->ajustes() ->where('tipo', 'reproceso')->sum('cantidad'); $cobros = (int) $tintoreria->cobros()->sum('cantidad'); $disponibles += ($recep - $reprocesos - $cobros); } $enviadasAcabados = $record->procesosAcabado()->sum('cantidad_enviada'); return max(0, $disponibles - $enviadasAcabados); } protected static function getEnBodega(OrdenProduccion $record): int { return $record->inventarioPrenda()->sum('cantidad_disponible'); } public static function getRelations(): array { return []; } public static function getPages(): array { return [ 'index' => Pages\ListSeguimientoProcesos::route('/'), ]; } }