F
Filament16mo ago
qcol

summarize and custom model attribute

Hi I have a model attribute: protected function sumRetail(): Attribute { return Attribute::make( get: fn () => $this->price_retail * $this->qty ); } And I would like to summarize the sum_retail column. With this notation, summarize does not work, but row summation works: TablesColumnsTextColumn::make('sum_retail')->label('Value.')->alignRight() ->summarize(Sum::make()->numeric(decimalPlaces: 2)), With this notation, summarize works, but row summation does not work. TablesColumnsTextColumn::make('price_retail * qty')->label('Value')->alignRight() ->summarize(Sum::make()->numeric(decimalPlaces: 2)), So how should this be correct?
Solution:
``` <?php namespace App\Tables\Components\Columns\Summarizers; ...
Jump to solution
4 Replies
Ian Tasker
Ian Tasker16mo ago
I am having the same issue. @qcol74 I think a custom version of sum is required. I'm going to try and write one and will let you know how I get on. @qcol74 Here is the attribute which will do what you want.
Solution
Ian Tasker
Ian Tasker16mo ago
<?php

namespace App\Tables\Components\Columns\Summarizers;

use Exception;
use Filament\Tables\Columns\Summarizers\Summarizer;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Schema;

class SumAttribute extends Summarizer
{
protected function setUp(): void
{
parent::setUp();

$this->numeric();
}

/**
* @return int | float | array<string, array<string, int>> | null
*/
public function summarize(Builder $query, string $attribute): int | float | array | null
{
$column = $this->getColumn();
$isField = Schema::hasColumn($this->getQuery()->getModel(), $column->getName());

if ($isField) {
throw new Exception("The [{$column->getName()}] column must be an Attribute.");
}

$limit = $this->getQuery()->getQuery()->limit;
$offset = $this->getQuery()->getQuery()->offset;
return $this->getQuery()->getModel()->get()->skip($offset)->take($limit)->pluck($attribute)->sum();
}
}
<?php

namespace App\Tables\Components\Columns\Summarizers;

use Exception;
use Filament\Tables\Columns\Summarizers\Summarizer;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Schema;

class SumAttribute extends Summarizer
{
protected function setUp(): void
{
parent::setUp();

$this->numeric();
}

/**
* @return int | float | array<string, array<string, int>> | null
*/
public function summarize(Builder $query, string $attribute): int | float | array | null
{
$column = $this->getColumn();
$isField = Schema::hasColumn($this->getQuery()->getModel(), $column->getName());

if ($isField) {
throw new Exception("The [{$column->getName()}] column must be an Attribute.");
}

$limit = $this->getQuery()->getQuery()->limit;
$offset = $this->getQuery()->getQuery()->offset;
return $this->getQuery()->getModel()->get()->skip($offset)->take($limit)->pluck($attribute)->sum();
}
}
qcol
qcolOP16mo ago
Thank you for this advice. I also found this solution: ->summarize( Summarizer::make() ->using(fn (Builder $query): string => $query->sum(DB::Raw('price_retail*qty'))) ->numeric(decimalPlaces: 2) )
mark.cameron
mark.cameron5mo ago
I'm not sure if they example custom sum above was for Filament v2.x or not, but it wasn't working properly on my v3.x, and was taking all models, not just those limited to the table I was displaying. Here's a different version based off the above example which I used for formatting the sums of Attributes for a money column, but that can easily be changed according to your needs.
<?php

namespace App\Filament\Components\Tables;

use Exception;
use Filament\Tables\Columns\Summarizers\Summarizer;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Schema;

class MoneySumAttribute extends Summarizer
{
protected function setUp(): void
{
parent::setUp();

$this->numeric()
->money(
config('filament-money-field.default_currency'),
100,
config('filament-money-field.default_locale')
);
}

/**
* @return int | float | array<string, array<string, int>> | null
*/
public function summarize(Builder $query, string $attribute): int | float | array | null
{
$column = $this->getColumn();
$isField = Schema::hasColumn($this->getQuery()->getModel(), $column->getName());

if ($isField) {
throw new Exception("The [{$column->getName()}] column must be an Attribute.");
}

$eloquentQuery = $this->getQuery()->getModel()->setQuery($query);
return $eloquentQuery->get()->pluck($attribute)->sum();
}

public function getDefaultLabel(): ?string
{
return __('filament-tables::table.summary.summarizers.sum.label');
}
}
<?php

namespace App\Filament\Components\Tables;

use Exception;
use Filament\Tables\Columns\Summarizers\Summarizer;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Schema;

class MoneySumAttribute extends Summarizer
{
protected function setUp(): void
{
parent::setUp();

$this->numeric()
->money(
config('filament-money-field.default_currency'),
100,
config('filament-money-field.default_locale')
);
}

/**
* @return int | float | array<string, array<string, int>> | null
*/
public function summarize(Builder $query, string $attribute): int | float | array | null
{
$column = $this->getColumn();
$isField = Schema::hasColumn($this->getQuery()->getModel(), $column->getName());

if ($isField) {
throw new Exception("The [{$column->getName()}] column must be an Attribute.");
}

$eloquentQuery = $this->getQuery()->getModel()->setQuery($query);
return $eloquentQuery->get()->pluck($attribute)->sum();
}

public function getDefaultLabel(): ?string
{
return __('filament-tables::table.summary.summarizers.sum.label');
}
}
Want results from more Discord servers?
Add your server