feat: Add real-time warehouse stock validation to DelayedGood and Order forms, supported by new WarehouseStock helper methods.
This commit is contained in:
parent
868a073fc2
commit
130571aeee
@ -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)
|
||||
|
||||
@ -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(),
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user