feat: Add real-time warehouse stock validation to DelayedGood and Order forms, supported by new WarehouseStock helper methods.

This commit is contained in:
Yoga Pangestu 2026-03-07 14:12:34 +07:00
parent 868a073fc2
commit 130571aeee
3 changed files with 68 additions and 2 deletions

View File

@ -2,7 +2,9 @@
namespace App\Filament\Resources\DelayedGoods\Schemas;
use App\Models\Unit;
use App\Models\Warehouse;
use App\Models\WarehouseStock;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
@ -79,6 +81,7 @@ public static function configure(Schema $schema): Schema
->preload()
->native(false)
->required()
->live()
->default(fn () => Warehouse::first()?->id),
Select::make('customer_id')
@ -103,6 +106,29 @@ public static function configure(Schema $schema): Schema
$recalculateTotal($get, $set);
$recalculateRemaining($get, $set);
})
->rules([
fn (callable $get, $record) => function (string $attribute, $value, $fail) use ($get, $record) {
$warehouseId = $get('warehouse_id');
$unitId = $get('unit_id');
$quantity = (float) str_replace(',', '.', $value);
if (! $warehouseId || ! $unitId || $quantity <= 0) {
return;
}
$available = WarehouseStock::getQuantity($warehouseId, $unitId);
// If we are editing, we add back the current quantity
if ($record && $record->warehouse_id == $warehouseId && $record->unit_id == $unitId) {
$available += (float) $record->quantity;
}
if ($available < $quantity) {
$unitAlias = Unit::find($unitId)?->alias ?? 'satuan';
$fail('Stok tidak mencukupi untuk unit ini di gudang tersebut. Tersedia: '.str_replace('.', ',', (float) $available)." {$unitAlias}");
}
},
])
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 2)
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
->dehydrateStateUsing($unmaskQty),
@ -127,7 +153,8 @@ public static function configure(Schema $schema): Schema
->searchable()
->preload()
->native(false)
->required(),
->required()
->live(),
]),
Grid::make(3)

View File

@ -11,7 +11,9 @@
use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Manage\Orders\Pages\ManageOrders;
use App\Models\Order;
use App\Models\Unit;
use App\Models\Warehouse;
use App\Models\WarehouseStock;
use BackedEnum;
use Filament\Actions\BulkActionGroup;
use Filament\Forms\Components\DatePicker;
@ -105,6 +107,7 @@ public static function form(Schema $schema): Schema
->preload()
->native(false)
->required()
->live()
->default(fn () => Warehouse::first()?->id),
Select::make('customer_id')
@ -128,6 +131,29 @@ public static function form(Schema $schema): Schema
->afterStateUpdated(function ($state, callable $get, callable $set) use ($recalculateTotal): void {
$recalculateTotal($get, $set);
})
->rules([
fn (callable $get, $record) => function (string $attribute, $value, $fail) use ($get, $record) {
$warehouseId = $get('warehouse_id');
$unitId = $get('unit_id');
$quantity = (float) str_replace(',', '.', $value);
if (! $warehouseId || ! $unitId || $quantity <= 0) {
return;
}
$available = WarehouseStock::getQuantity($warehouseId, $unitId);
// If we are editing, we add back the current quantity
if ($record && $record->warehouse_id == $warehouseId && $record->unit_id == $unitId) {
$available += (float) $record->egg_quantity;
}
if ($available < $quantity) {
$unitAlias = Unit::find($unitId)?->alias ?? 'satuan';
$fail('Stok tidak mencukupi untuk unit ini di gudang tersebut. Tersedia: '.str_replace('.', ',', (float) $available)." {$unitAlias}");
}
},
])
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 2)
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
->dehydrateStateUsing($unmaskQty),
@ -151,7 +177,8 @@ public static function form(Schema $schema): Schema
->searchable()
->preload()
->native(false)
->required(),
->required()
->live(),
])
->columnSpanFull(),

View File

@ -40,4 +40,16 @@ public static function adjustStock(int $warehouseId, int $unitId, bool $isBroken
$stock->increment('quantity', $quantity);
}
public static function getQuantity(int $warehouseId, int $unitId): float
{
return (float) (self::where('warehouse_id', $warehouseId)
->where('unit_id', $unitId)
->first()?->quantity ?? 0);
}
public static function hasSufficientStock(int $warehouseId, int $unitId, float|int $neededQuantity): bool
{
return self::getQuantity($warehouseId, $unitId) >= $neededQuantity;
}
}