user()?->can('ver ojals') ?? false; } public static function form(Forms\Form $form): Forms\Form { return $form->schema([ Select::make('tipo') ->label('Tipo de Proceso') ->options([ 'Ojal' => 'Ojal', 'Prensilla' => 'Prensilla', ]) ->required() ->reactive() ->helperText(fn ($get) => $get('tipo') === 'Prensilla' ? '⚠️ Solo se pueden enviar prendas que hayan terminado el proceso de Ojales' : 'Primer proceso: las prendas vienen desde Confección'), Select::make('orden_produccion_id') ->label('Orden de Producción') ->options(function ($get) { $tipo = $get('tipo'); if ($tipo === 'Prensilla') { // Para Prensillas: mostrar OPs con ojales terminados return \App\Models\OrdenProduccion::whereHas('ojales', function ($q) { $q->where('terminada', true); })->get()->mapWithKeys(function ($op) { // Calcular ojales terminados menos prensillas ya enviadas $ojalesTerminados = \App\Models\Ojal::where('orden_produccion_id', $op->id) ->where('terminada', true) ->sum('cantidad_enviada'); $yaEnviado = \App\Models\Prensilla::where('orden_produccion_id', $op->id) ->sum('cantidad_enviada'); $disponible = $ojalesTerminados - $yaEnviado; if ($disponible > 0) { return [$op->id => "{$op->numero_orden} (Disponible: {$disponible})"]; } return []; })->filter(); } else { // Para Ojales: mostrar OPs con confecciones disponibles return \App\Models\OrdenProduccion::whereHas('confecciones', function ($q) { $q->where('cantidad_recibida', '>', 0); })->get()->mapWithKeys(function ($op) { $cantidadRecibida = $op->confecciones->sum('cantidad_recibida'); $arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($op) { $q->where('orden_produccion_id', $op->id); })->where('tipo', 'arreglo')->sum('cantidad'); $cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($op) { $q->where('orden_produccion_id', $op->id); })->sum('cantidad'); $cantidadConfecciones = $cantidadRecibida - $arreglos - $cobros; $cantidadEnOjales = \App\Models\Ojal::where('orden_produccion_id', $op->id) ->sum('cantidad_enviada'); $saldoDisponible = $cantidadConfecciones - $cantidadEnOjales; if ($saldoDisponible > 0) { return [$op->id => "{$op->numero_orden} (Disponible: {$saldoDisponible})"]; } return []; })->filter(); } }) ->searchable() ->required() ->reactive() ->afterStateUpdated(function ($state, $set, $get) { $tipo = $get('tipo'); if (!$state || !$tipo) return; $op = \App\Models\OrdenProduccion::find($state); if (!$op) return; // Calcular cantidad disponible según el tipo if ($tipo === 'Ojal') { // Para ojales: desde confecciones $cantidadRecibida = $op->confecciones->sum('cantidad_recibida'); $arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($state) { $q->where('orden_produccion_id', $state); })->where('tipo', 'arreglo')->sum('cantidad'); $cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($state) { $q->where('orden_produccion_id', $state); })->sum('cantidad'); $cantidadConfecciones = $cantidadRecibida - $arreglos - $cobros; $cantidadEnOjales = \App\Models\Ojal::where('orden_produccion_id', $state) ->sum('cantidad_enviada'); $cantidadDisponible = $cantidadConfecciones - $cantidadEnOjales; } else { // Para prensillas: desde ojales terminados $ojalesTerminados = \App\Models\Ojal::where('orden_produccion_id', $state) ->where('terminada', true) ->sum('cantidad_enviada'); $yaEnviado = \App\Models\Prensilla::where('orden_produccion_id', $state) ->sum('cantidad_enviada'); $cantidadDisponible = $ojalesTerminados - $yaEnviado; } $set('cantidad_enviada', max(0, $cantidadDisponible)); $set('prenda_nombre_info', $op->prenda_modelo ?? 'Sin especificar'); }) ->helperText('Solo se muestran órdenes con prendas disponibles para enviar'), TextInput::make('prenda_nombre_info') ->label('Prenda') ->disabled() ->dehydrated(false) ->visible(fn ($get) => $get('orden_produccion_id') !== null) ->helperText('Nombre de la prenda de la orden de producción seleccionada'), Select::make('proveedor_id') ->label('Proveedor/Usuario Principal') ->options(fn() => \App\Models\Proveedor::where('categoria', 'empleado')->pluck('nombre', 'id')) ->searchable() ->preload() ->required() ->helperText('Selecciona el empleado responsable del proceso'), TextInput::make('cantidad_enviada') ->label('Cantidad') ->numeric() ->required() ->minValue(1) ->reactive() ->helperText(function ($get) { $opId = $get('orden_produccion_id'); $tipo = $get('tipo'); if (!$opId || !$tipo) return 'Selecciona una OP y tipo primero'; $op = \App\Models\OrdenProduccion::find($opId); if (!$op) return ''; if ($tipo === 'Ojal') { $cantidadRecibida = $op->confecciones->sum('cantidad_recibida'); $arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($opId) { $q->where('orden_produccion_id', $opId); })->where('tipo', 'arreglo')->sum('cantidad'); $cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class) ->whereHas('referencia', function($q) use ($opId) { $q->where('orden_produccion_id', $opId); })->sum('cantidad'); $cantidadConfecciones = $cantidadRecibida - $arreglos - $cobros; $yaEnviado = \App\Models\Ojal::where('orden_produccion_id', $opId)->sum('cantidad_enviada'); $disponible = $cantidadConfecciones - $yaEnviado; return "Disponible desde Confección: {$disponible}"; } else { $ojalesTerminados = \App\Models\Ojal::where('orden_produccion_id', $opId) ->where('terminada', true)->sum('cantidad_enviada'); $yaEnviado = \App\Models\Prensilla::where('orden_produccion_id', $opId)->sum('cantidad_enviada'); $disponible = $ojalesTerminados - $yaEnviado; return "Disponible desde Ojales terminados: {$disponible}"; } }), Checkbox::make('terminada') ->label('Marcar como terminado') ->helperText(fn ($get) => $get('tipo') === 'Prensilla' ? '✓ Al terminar Prensillas, las prendas quedarán disponibles para Tintorería' : '✓ Al terminar Ojales, las prendas quedarán disponibles para Prensillas') ->reactive(), ]); } public static function table(Tables\Table $table): Tables\Table { return $table ->columns([ Tables\Columns\TextColumn::make('tipo') ->label('Proceso') ->searchable() ->sortable() ->badge() ->color(fn ($state) => $state === 'Ojal' ? 'info' : 'warning'), Tables\Columns\TextColumn::make('ordenProduccion.numero_orden') ->label('OP') ->searchable() ->sortable(), Tables\Columns\TextColumn::make('ordenProduccion.referencia') ->label('Referencia') ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('ordenProduccion.prenda_modelo') ->label('Prenda') ->searchable() ->limit(30) ->toggleable(), Tables\Columns\TextColumn::make('cantidad_enviada') ->label('Cantidad') ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('proveedor.nombre') ->label('Proveedor') ->searchable() ->toggleable() ->default('Sin asignar'), Tables\Columns\TextColumn::make('usuarioAsignado.name') ->label('Operario') ->searchable() ->toggleable() ->default('-'), Tables\Columns\IconColumn::make('terminada') ->boolean() ->label('Terminado') ->alignCenter() ->sortable(), Tables\Columns\BadgeColumn::make('estado_flujo') ->label('Estado en Flujo') ->getStateUsing(function ($record) { if ($record->tipo === 'Ojal') { if ($record->terminada) { // Verificar si ya se creó el proceso de prensillas $prensillasCreadas = \App\Models\Prensilla::where('orden_produccion_id', $record->orden_produccion_id) ->where('cantidad_enviada', '>', 0) ->exists(); return $prensillasCreadas ? 'En Prensillas' : 'Listo para Prensillas'; } return 'En Proceso'; } else { // Es Prensilla if ($record->terminada) { return 'Listo para Tintorería'; } return 'En Proceso'; } }) ->colors([ 'success' => fn ($state) => in_array($state, ['Listo para Prensillas', 'Listo para Tintorería']), 'primary' => 'En Prensillas', 'warning' => 'En Proceso', ]), Tables\Columns\TextColumn::make('fecha_envio') ->date() ->label('Fecha envío') ->sortable(), Tables\Columns\TextColumn::make('created_at') ->dateTime() ->label('Creado') ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->filters([ SelectFilter::make('tipo') ->label('Tipo de Proceso') ->options([ 'Ojal' => 'Ojal', 'Prensilla' => 'Prensilla', ]), SelectFilter::make('terminada') ->label('Estado') ->options([ '0' => 'En Proceso', '1' => 'Terminado', ]), SelectFilter::make('proveedor_id') ->label('Proveedor') ->relationship('proveedor', 'nombre'), SelectFilter::make('usuario_asignado_id') ->label('Operario') ->relationship('usuarioAsignado', 'name'), ]) ->actions([ Tables\Actions\EditAction::make(), Tables\Actions\Action::make('marcar_terminada') ->label('Terminar') ->icon('heroicon-o-check-circle') ->color('success') ->visible(fn ($record) => !$record->terminada) ->requiresConfirmation() ->modalHeading('Marcar como terminado') ->modalDescription('¿Confirmas que este proceso ha terminado?') ->action(function ($record) { $record->terminada = true; $record->save(); \Filament\Notifications\Notification::make() ->success() ->title('Marcado como terminado') ->send(); }), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make(), ]), ]) ->defaultSort('created_at', 'desc'); } public static function getPages(): array { return [ 'index' => Pages\ListOjalPresillas::route('/'), 'create' => Pages\CreateOjalPresilla::route('/create'), 'edit' => Pages\EditOjalPresilla::route('/{record}/edit'), ]; } }