diff --git a/app/Filament/Resources/DelayedGoods/Schemas/DelayedGoodForm.php b/app/Filament/Resources/DelayedGoods/Schemas/DelayedGoodForm.php index 25eedb5..7d676ce 100644 --- a/app/Filament/Resources/DelayedGoods/Schemas/DelayedGoodForm.php +++ b/app/Filament/Resources/DelayedGoods/Schemas/DelayedGoodForm.php @@ -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) diff --git a/app/Filament/Resources/Manage/Orders/OrderResource.php b/app/Filament/Resources/Manage/Orders/OrderResource.php index 2daa650..397cfc0 100644 --- a/app/Filament/Resources/Manage/Orders/OrderResource.php +++ b/app/Filament/Resources/Manage/Orders/OrderResource.php @@ -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(), diff --git a/app/Models/WarehouseStock.php b/app/Models/WarehouseStock.php index d320ee4..77bfc8a 100644 --- a/app/Models/WarehouseStock.php +++ b/app/Models/WarehouseStock.php @@ -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; + } }