Currently, we have Customers and Pipeline Stages in our system. Still, there is no easy way to move our Customers within the Pipeline while saving its history. Let's fix that by adding a table Action:

In this lesson, we will do the following:
CustomerPipelineStage Model to save the history of the Customer's Pipeline Stage changes and any comments added.Our CustomerPipelineStage Model will be a simple table with the following fields:
customer_id - the Customer IDpipeline_stage_id (nullable) - the Pipeline Stage ID. It is nullable to allow notes without status change.user_id (nullable) - the User who made the change. It is nullable to allow system-triggered changes to be logged.notes (nullable, text) - any notes added to the changeLet's create the Migration:
Migration
use App\Models\Customer;use App\Models\PipelineStage;use App\Models\User; // ... Schema::create('customer_pipeline_stages', function (Blueprint $table) {    $table->id();    $table->foreignIdFor(Customer::class)->constrained();    $table->foreignIdFor(PipelineStage::class)->nullable()->constrained();    $table->foreignIdFor(User::class)->nullable()->constrained();    $table->text('notes')->nullable();    $table->timestamps();});Next, we will create the Model:
app/Models/CustomerPipelineStage.php
use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsTo; class CustomerPipelineStage extends Model{    protected $fillable = [        'customer_id',        'pipeline_stage_id',        'user_id',        'notes'    ];     public function user(): BelongsTo    {        return $this->belongsTo(User::class);    }     public function customer(): BelongsTo    {        return $this->belongsTo(Customer::class);    }     public function pipelineStage(): BelongsTo    {        return $this->belongsTo(PipelineStage::class);    }}And finally, we will add the relationship to our Customer Model:
app/Models/Customer.php
use Illuminate\Database\Eloquent\Relations\HasMany; // ... public function pipelineStageLogs(): HasMany{    return $this->hasMany(CustomerPipelineStage::class);}That's it. We can run:
php artisan migrate:fresh --seedAnd have the Database table ready for our customer logs.
Now that we have our Database and Models ready, we can implement the table Action:
use Filament\Notifications\Notification; // ... public static function table(Table $table): Table{    return $table        ->columns([            // ...        ])        ->filters([            // ...        ])        ->actions([            Tables\Actions\EditAction::make(),            Tables\Actions\Action::make('Move to Stage')                ->icon('heroicon-m-pencil-square')                ->form([                    Forms\Components\Select::make('pipeline_stage_id')                        ->label('Status')                        ->options(PipelineStage::pluck('name', 'id')->toArray())                        ->default(function (Customer $record) {                            $currentPosition = $record->pipelineStage->position;                            return PipelineStage::where('position', '>', $currentPosition)->first()?->id;                        }),                    Forms\Components\Textarea::make('notes')                        ->label('Notes')                ])                ->action(function (Customer $customer, array $data): void {                    $customer->pipeline_stage_id = $data['pipeline_stage_id'];                    $customer->save();                     $customer->pipelineStageLogs()->create([                        'pipeline_stage_id' => $data['pipeline_stage_id'],                        'notes' => $data['notes'],                        'user_id' => auth()->id()                    ]);                     Notification::make()                        ->title('Customer Pipeline Updated')                        ->success()                        ->send();                }),        ])        ->bulkActions([            // ...        ]);} // ...Few things to note here:
notes are being written into a temporary field that will be removed from the Model at the update event.Here's what this looks like in the UI:

The last thing to do is to create the Observers to log all the Pipeline Stage changes:
app/Models/Customer.php
// ... public static function booted(): void{    self::created(function (Customer $customer) {        $customer->pipelineStageLogs()->create([            'pipeline_stage_id' => $customer->pipeline_stage_id,            'user_id' => auth()->check() ? auth()->id() : null        ]);    });} // ...This is going to listen for create event and do the following:
CustomerPipelineStage record with the pipeline_stage_id and user_id (if logged in) from the Customer.That's it. In the next lesson, we will build the table filters.