feat: Enhance WarehouseResource with stock management features, including a repeater for stock entries and improved quantity handling in the WarehouseStock model

This commit is contained in:
Yoga Pangestu 2026-03-07 12:03:12 +07:00
parent c6e7119b94
commit 0a643efbb6
5 changed files with 56 additions and 35 deletions

View File

@ -13,6 +13,8 @@
use App\Models\Warehouse;
use BackedEnum;
use Filament\Actions\BulkActionGroup;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
@ -46,11 +48,47 @@ public static function form(Schema $schema): Schema
return $schema
->components([
TextInput::make('name')
->label('Nama Gudang')
->label('Nama')
->placeholder('Gudang Utama')
->autocomplete(false)
->required()
->maxLength(30),
Repeater::make('stocks')
->label('Stok Telur')
->relationship('stocks')
->schema([
Select::make('unit_id')
->label('Satuan')
->relationship('unit', 'name')
->required()
->searchable()
->preload(),
TextInput::make('quantity')
->label('Jumlah')
->placeholder('0')
->autocomplete(false)
->required()
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 2)
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
->dehydrateStateUsing(function ($state) {
if (blank($state)) {
return 0;
}
if (is_numeric($state)) {
return (float) $state;
}
return (float) str($state)
->replace('.', '')
->replace(',', '.')
->toString();
}),
])
->columns(2)
->addActionLabel('Tambah Stok')
->columnSpanFull(),
])
->columns(1);
}
@ -60,22 +98,23 @@ public static function table(Table $table): Table
return $table
->columns([
TextColumn::make('name')
->label('Nama Gudang')
->label('Nama')
->searchable()
->sortable(),
TextColumn::make('stocks')
->label('Stok Telur')
->label('Stok')
->getStateUsing(function (Warehouse $record) {
return $record->stocks()
->where('quantity', '>', 0)
->with('unit')
->get()
->map(fn ($stock) => (float) $stock->quantity.' '.$stock->unit?->alias.($stock->is_broken ? ' (Pecah)' : ''))
->join(', ') ?: 'Kosong';
->map(fn ($stock) => str_replace('.', ',', (float) $stock->quantity).' '.$stock->unit?->alias)
->toArray();
})
->badge()
->color('info'),
->listWithLineBreaks()
->color('info')
->placeholder('Kosong'),
...TimestampColumns::make(),
])
@ -86,7 +125,7 @@ public static function table(Table $table): Table
])
->recordActions([
EditAction::make()
->modalWidth(Width::Large),
->modalWidth(Width::FourExtraLarge),
DeleteAction::make(),

View File

@ -11,6 +11,10 @@ class WarehouseStock extends Model
protected $guarded = ['id'];
protected $casts = [
'quantity' => 'decimal:2',
];
public function warehouse()
{
return $this->belongsTo(Warehouse::class);
@ -23,10 +27,13 @@ public function unit()
public static function adjustStock(int $warehouseId, int $unitId, bool $isBroken, float $quantity): void
{
if ($isBroken) {
return;
}
$stock = self::firstOrCreate([
'warehouse_id' => $warehouseId,
'unit_id' => $unitId,
'is_broken' => $isBroken,
], [
'quantity' => 0,
]);

View File

@ -12,11 +12,10 @@ public function up(): void
$table->id();
$table->foreignId('warehouse_id')->constrained()->cascadeOnDelete();
$table->foreignId('unit_id')->constrained()->cascadeOnDelete();
$table->boolean('is_broken')->default(false);
$table->decimal('quantity', 12, 2)->default(0);
$table->timestamps();
$table->unique(['warehouse_id', 'unit_id', 'is_broken'], 'warehouse_unit_condition_unique');
$table->unique(['warehouse_id', 'unit_id'], 'warehouse_unit_unique');
});
}

View File

@ -1,24 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('egg_collections', function (Blueprint $table) {
$table->decimal('total_eggs', 12, 2)->default(0)->change();
$table->decimal('total_broken_eggs', 12, 2)->default(0)->change();
});
}
public function down(): void
{
Schema::table('egg_collections', function (Blueprint $table) {
$table->unsignedInteger('total_eggs')->default(0)->change();
$table->unsignedInteger('total_broken_eggs')->default(0)->change();
});
}
};