ifnex/04_Laravel/app/Filament/Resources/CustomerCreditResource.php
Kazem Alghasi eda3110ac1 fix(ui): fix filter state handling in Filament resources and remove soft deletes
Handle array-based filter states in CustomerCreditResource and
ShipmentChecklistResource to ensure correct query execution.
Also remove SoftDeletes trait from ShipmentChecklist model.
2026-09-03 08:01:00 +03:30

248 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Filament\Resources;
use App\Filament\Resources\CustomerCreditResource\Pages;
use App\Models\User;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
class CustomerCreditResource extends Resource
{
protected static ?string $model = User::class;
protected static ?string $navigationIcon = 'heroicon-o-banknotes';
protected static ?string $navigationGroup = 'مدیریت مالی';
protected static ?string $navigationLabel = 'اعتبار مشتریان';
protected static ?string $modelLabel = 'اعتبار مشتری';
protected static ?string $pluralModelLabel = 'اعتبار مشتریان';
protected static ?int $navigationSort = 10;
public static function form(Form $form): Form
{
return $form->schema([
Forms\Components\Section::make('اطلاعات مشتری')
->schema([
Forms\Components\TextInput::make('name')
->label('نام')
->disabled(),
Forms\Components\TextInput::make('email')
->label('ایمیل')
->disabled(),
Forms\Components\TextInput::make('phone')
->label('موبایل')
->disabled(),
])->columns(3),
Forms\Components\Section::make('اطلاعات اعتبار')
->schema([
Forms\Components\TextInput::make('credit_limit')
->label('سقف اعتبار (ریال)')
->numeric()
->default(0)
->minValue(0)
->required(),
Forms\Components\TextInput::make('credit_used')
->label('مبلغ استفاده شده (ریال)')
->numeric()
->default(0)
->disabled(),
Forms\Components\TextInput::make('available_credit')
->label('اعتبار باقیمانده (ریال)')
->numeric()
->disabled()
->dehydrated(false),
])->columns(3),
Forms\Components\Section::make('تاریخچه تراکنش‌ها')
->schema([
Forms\Components\Placeholder::make('transactions_history')
->label('تراکنش‌های اخیر')
->content(function ($record) {
if (!$record) return '-';
$transactions = DB::table('wallet_transactions')
->where('user_id', $record->id)
->orderBy('created_at', 'desc')
->take(5)
->get();
if ($transactions->isEmpty()) return 'تراکنشی ثبت نشده';
$html = '<div style="font-size: 12px; line-height: 1.8;">';
foreach ($transactions as $tx) {
$type = match($tx->type) {
'credit_add' => ' افزایش اعتبار',
'credit_use' => ' استفاده از اعتبار',
default => $tx->type,
};
$html .= '<div>' . $type . ': ' . number_format($tx->amount) . ' ریال - ' . $tx->description . '</div>';
}
$html .= '</div>';
return $html;
}),
]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')
->label('شناسه')
->sortable(),
Tables\Columns\TextColumn::make('name')
->label('نام')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('email')
->label('ایمیل')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('phone')
->label('موبایل')
->searchable(),
Tables\Columns\TextColumn::make('credit_limit')
->label('سقف اعتبار')
->numeric()
->formatStateUsing(fn ($state) => number_format($state) . ' ریال')
->sortable(),
Tables\Columns\TextColumn::make('credit_used')
->label('استفاده شده')
->numeric()
->formatStateUsing(fn ($state) => number_format($state) . ' ریال')
->sortable(),
Tables\Columns\TextColumn::make('available_credit')
->label('باقیمانده')
->numeric()
->formatStateUsing(fn ($state) => number_format($state) . ' ریال')
->color(fn ($state) => $state > 0 ? 'success' : 'danger')
->sortable(),
])
->filters([
Tables\Filters\SelectFilter::make('has_credit')
->label('وضعیت اعتبار')
->options([
'has_limit' => 'دارای سقف اعتبار',
'no_limit' => 'بدون سقف اعتبار',
'has_used' => 'استفاده شده',
'has_available' => 'باقیمانده',
])
->query(function ($query, $filter) {
$state = $filter->getState();
if (is_array($state)) {
$state = $state['value'] ?? null;
}
match ($state) {
'has_limit' => $query->where('credit_limit', '>', 0),
'no_limit' => $query->where('credit_limit', 0),
'has_used' => $query->where('credit_used', '>', 0),
'has_available' => $query->whereRaw('credit_limit - credit_used > 0'),
default => null,
};
}),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\Action::make('add_credit')
->label('افزایش اعتبار')
->icon('heroicon-o-plus-circle')
->color('success')
->form([
Forms\Components\TextInput::make('amount')
->label('مبلغ (ریال)')
->numeric()
->required()
->minValue(1),
Forms\Components\TextInput::make('description')
->label('توضیحات')
->required(),
])
->action(function ($record, array $data): void {
DB::beginTransaction();
try {
$record->credit_limit += $data['amount'];
$record->save();
DB::table('wallet_transactions')->insert([
'user_id' => $record->id,
'type' => 'credit_add',
'amount' => $data['amount'],
'description' => $data['description'],
'created_at' => now(),
'updated_at' => now(),
]);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
}),
Tables\Actions\Action::make('reduce_credit')
->label('کاهش اعتبار')
->icon('heroicon-o-minus-circle')
->color('danger')
->form([
Forms\Components\TextInput::make('amount')
->label('مبلغ (ریال)')
->numeric()
->required()
->minValue(1),
Forms\Components\TextInput::make('description')
->label('توضیحات')
->required(),
])
->action(function ($record, array $data): void {
DB::beginTransaction();
try {
$record->credit_limit -= $data['amount'];
$record->save();
DB::table('wallet_transactions')->insert([
'user_id' => $record->id,
'type' => 'credit_reduce',
'amount' => $data['amount'],
'description' => $data['description'],
'created_at' => now(),
'updated_at' => now(),
]);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
}),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [];
}
public static function getPages(): array
{
return [
'index' => Pages\ListCustomerCredits::route('/'),
'edit' => Pages\EditCustomerCredit::route('/{record}/edit'),
];
}
public static function getNavigationBadge(): ?string
{
return static::getModel()::where('credit_limit', '>', 0)->count();
}
}