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;
|
namespace App\Filament\Resources\DelayedGoods\Schemas;
|
||||||
|
|
||||||
|
use App\Models\Unit;
|
||||||
use App\Models\Warehouse;
|
use App\Models\Warehouse;
|
||||||
|
use App\Models\WarehouseStock;
|
||||||
use Filament\Forms\Components\DatePicker;
|
use Filament\Forms\Components\DatePicker;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
use Filament\Forms\Components\Textarea;
|
use Filament\Forms\Components\Textarea;
|
||||||
@ -79,6 +81,7 @@ public static function configure(Schema $schema): Schema
|
|||||||
->preload()
|
->preload()
|
||||||
->native(false)
|
->native(false)
|
||||||
->required()
|
->required()
|
||||||
|
->live()
|
||||||
->default(fn () => Warehouse::first()?->id),
|
->default(fn () => Warehouse::first()?->id),
|
||||||
|
|
||||||
Select::make('customer_id')
|
Select::make('customer_id')
|
||||||
@ -103,6 +106,29 @@ public static function configure(Schema $schema): Schema
|
|||||||
$recalculateTotal($get, $set);
|
$recalculateTotal($get, $set);
|
||||||
$recalculateRemaining($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)
|
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 2)
|
||||||
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
|
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
|
||||||
->dehydrateStateUsing($unmaskQty),
|
->dehydrateStateUsing($unmaskQty),
|
||||||
@ -127,7 +153,8 @@ public static function configure(Schema $schema): Schema
|
|||||||
->searchable()
|
->searchable()
|
||||||
->preload()
|
->preload()
|
||||||
->native(false)
|
->native(false)
|
||||||
->required(),
|
->required()
|
||||||
|
->live(),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
Grid::make(3)
|
Grid::make(3)
|
||||||
|
|||||||
@ -11,7 +11,9 @@
|
|||||||
use App\Filament\Columns\TimestampColumns;
|
use App\Filament\Columns\TimestampColumns;
|
||||||
use App\Filament\Resources\Manage\Orders\Pages\ManageOrders;
|
use App\Filament\Resources\Manage\Orders\Pages\ManageOrders;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
|
use App\Models\Unit;
|
||||||
use App\Models\Warehouse;
|
use App\Models\Warehouse;
|
||||||
|
use App\Models\WarehouseStock;
|
||||||
use BackedEnum;
|
use BackedEnum;
|
||||||
use Filament\Actions\BulkActionGroup;
|
use Filament\Actions\BulkActionGroup;
|
||||||
use Filament\Forms\Components\DatePicker;
|
use Filament\Forms\Components\DatePicker;
|
||||||
@ -105,6 +107,7 @@ public static function form(Schema $schema): Schema
|
|||||||
->preload()
|
->preload()
|
||||||
->native(false)
|
->native(false)
|
||||||
->required()
|
->required()
|
||||||
|
->live()
|
||||||
->default(fn () => Warehouse::first()?->id),
|
->default(fn () => Warehouse::first()?->id),
|
||||||
|
|
||||||
Select::make('customer_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 {
|
->afterStateUpdated(function ($state, callable $get, callable $set) use ($recalculateTotal): void {
|
||||||
$recalculateTotal($get, $set);
|
$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)
|
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 2)
|
||||||
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
|
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
|
||||||
->dehydrateStateUsing($unmaskQty),
|
->dehydrateStateUsing($unmaskQty),
|
||||||
@ -151,7 +177,8 @@ public static function form(Schema $schema): Schema
|
|||||||
->searchable()
|
->searchable()
|
||||||
->preload()
|
->preload()
|
||||||
->native(false)
|
->native(false)
|
||||||
->required(),
|
->required()
|
||||||
|
->live(),
|
||||||
])
|
])
|
||||||
->columnSpanFull(),
|
->columnSpanFull(),
|
||||||
|
|
||||||
|
|||||||
@ -40,4 +40,16 @@ public static function adjustStock(int $warehouseId, int $unitId, bool $isBroken
|
|||||||
|
|
||||||
$stock->increment('quantity', $quantity);
|
$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