schema([ DateTimePicker::make('fecha_recepcion') ->label('Fecha de Recepción') ->required() ->default(now()), Forms\Components\Select::make('proveedor_id') ->label('Proveedor') ->options(function () { $proceso = $this->getOwnerRecord(); if (!$proceso || !$proceso->distribucion_proveedores) { return []; } $opciones = []; foreach ($proceso->distribucion_proveedores as $dist) { $proveedorId = $dist['proveedor_id'] ?? null; if ($proveedorId) { $proveedor = \App\Models\Proveedor::find($proveedorId); if ($proveedor) { $opciones[$proveedorId] = $proveedor->nombre; } } } return $opciones; }) ->reactive() ->required() ->afterStateUpdated(function ($state, $set, $get) { // Calcular cantidad disponible para este proveedor $proceso = $this->getOwnerRecord(); if (!$proceso || !$state) return; // Buscar la cantidad asignada a este proveedor $cantidadAsignada = 0; foreach ($proceso->distribucion_proveedores ?? [] as $dist) { if (($dist['proveedor_id'] ?? null) == $state) { $cantidadAsignada = (int) ($dist['cantidad'] ?? 0); break; } } // Calcular cuánto ya se ha recibido de este proveedor $yaRecibido = (int) $proceso->recepciones() ->where('proveedor_id', $state) ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $disponible = max(0, $cantidadAsignada - $yaRecibido); $set('_max_cantidad', $disponible); }) ->helperText(function ($get) { $proveedorId = $get('proveedor_id'); if (!$proveedorId) return 'Selecciona un proveedor para ver la cantidad disponible'; $proceso = $this->getOwnerRecord(); if (!$proceso) return ''; // Buscar cantidad asignada $cantidadAsignada = 0; foreach ($proceso->distribucion_proveedores ?? [] as $dist) { if (($dist['proveedor_id'] ?? null) == $proveedorId) { $cantidadAsignada = (int) ($dist['cantidad'] ?? 0); break; } } // Calcular ya recibido $yaRecibido = (int) $proceso->recepciones() ->where('proveedor_id', $proveedorId) ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $disponible = max(0, $cantidadAsignada - $yaRecibido); return "Asignado: {$cantidadAsignada} | Ya recibido: {$yaRecibido} | Disponible: {$disponible}"; }), TextInput::make('cantidad') ->label('Cantidad Recibida') ->numeric() ->required() ->minValue(1) ->maxValue(function ($get) { $proveedorId = $get('proveedor_id'); if (!$proveedorId) return 0; $proceso = $this->getOwnerRecord(); if (!$proceso) return 0; // Buscar cantidad asignada $cantidadAsignada = 0; foreach ($proceso->distribucion_proveedores ?? [] as $dist) { if (($dist['proveedor_id'] ?? null) == $proveedorId) { $cantidadAsignada = (int) ($dist['cantidad'] ?? 0); break; } } // Calcular ya recibido $yaRecibido = (int) $proceso->recepciones() ->where('proveedor_id', $proveedorId) ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); return max(0, $cantidadAsignada - $yaRecibido); }) ->helperText(function ($get) { $proveedorId = $get('proveedor_id'); if (!$proveedorId) return 'Primero selecciona un proveedor'; $proceso = $this->getOwnerRecord(); if (!$proceso) return ''; // Buscar cantidad asignada $cantidadAsignada = 0; foreach ($proceso->distribucion_proveedores ?? [] as $dist) { if (($dist['proveedor_id'] ?? null) == $proveedorId) { $cantidadAsignada = (int) ($dist['cantidad'] ?? 0); break; } } // Calcular ya recibido $yaRecibido = (int) $proceso->recepciones() ->where('proveedor_id', $proveedorId) ->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $disponible = max(0, $cantidadAsignada - $yaRecibido); return 'Máximo disponible de este proveedor: ' . $disponible; }), TextInput::make('prendas_defectuosas') ->label('Prendas Defectuosas') ->numeric() ->default(0) ->minValue(0) ->helperText('Si hay prendas defectuosas, regístralas aquí. Estas no pasarán al inventario.'), Textarea::make('notas') ->label('Notas / Observaciones') ->rows(3) ->maxLength(65535), ]); } public function table(Tables\Table $table): Tables\Table { return $table ->columns([ TextColumn::make('id') ->label('#') ->sortable(), TextColumn::make('fecha_recepcion') ->label('Fecha Recepción') ->dateTime('d/m/Y H:i') ->sortable(), TextColumn::make('proveedor.nombre') ->label('Proveedor') ->searchable() ->toggleable(), TextColumn::make('cantidad') ->label('Cantidad') ->sortable(), TextColumn::make('prendas_defectuosas') ->label('Defectuosas') ->default(0) ->badge() ->color(fn ($state) => $state > 0 ? 'danger' : 'gray'), TextColumn::make('cantidad_efectiva') ->label('Cantidad Efectiva') ->getStateUsing(fn ($record) => $record->cantidad - ($record->prendas_defectuosas ?? 0)) ->badge() ->color('success'), TextColumn::make('notas') ->label('Notas') ->limit(50) ->wrap() ->toggleable(), TextColumn::make('created_at') ->label('Creado') ->dateTime('d/m/Y H:i') ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->defaultSort('fecha_recepcion', 'desc') ->headerActions([ CreateAction::make() ->label('Nueva Recepción') ->icon('heroicon-o-plus-circle') ->disabled(fn () => ($this->getOwnerRecord()?->faltantes ?? 0) <= 0) ->mutateFormDataUsing(function (array $data): array { // Asignar usuario actual $data['user_id'] = Auth::id(); return $data; }), ]) ->actions([ EditAction::make(), DeleteAction::make(), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make(), ]), ]) ->emptyStateHeading('Sin recepciones registradas') ->emptyStateDescription('Las recepciones quedarán disponibles automáticamente para el inventario de prendas.') ->emptyStateIcon('heroicon-o-inbox-arrow-down'); } }