feat: Integrate warehouse management and decimal quantities for delayed goods, with automatic stock adjustments.

This commit is contained in:
Yoga Pangestu 2026-03-07 13:49:21 +07:00
parent 0ab5b19dc2
commit 39593b7170
5 changed files with 82 additions and 4 deletions

View File

@ -2,6 +2,7 @@
namespace App\Filament\Resources\DelayedGoods\Schemas;
use App\Models\Warehouse;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
@ -62,7 +63,7 @@ public static function configure(Schema $schema): Schema
};
return $schema->components([
Grid::make(2)
Grid::make(3)
->schema([
DatePicker::make('stored_date')
->label('Tanggal Penyimpanan')
@ -71,6 +72,15 @@ public static function configure(Schema $schema): Schema
->native(false)
->displayFormat('l, d F Y'),
Select::make('warehouse_id')
->label('Ambil Dari Gudang')
->relationship('warehouse', 'name')
->searchable()
->preload()
->native(false)
->required()
->default(fn () => Warehouse::first()?->id),
Select::make('customer_id')
->label('Pelanggan')
->relationship('customer', 'name')
@ -78,7 +88,8 @@ public static function configure(Schema $schema): Schema
->preload()
->native(false)
->required(),
]),
])
->columnSpanFull(),
Grid::make(3)
->schema([

View File

@ -34,6 +34,11 @@ public static function configure(Table $table): Table
->searchable()
->sortable(),
TextColumn::make('warehouse.name')
->label('Gudang')
->searchable()
->sortable(),
TextColumn::make('quantity')
->label('Jumlah')
->getStateUsing(function ($record) {

View File

@ -21,7 +21,7 @@ protected function casts(): array
return [
'stored_date' => 'date',
'payment_date' => 'date',
'quantity' => 'integer',
'quantity' => 'decimal:2',
'unit_price' => 'integer',
'total_amount' => 'integer',
'paid_amount' => 'integer',
@ -38,4 +38,9 @@ public function unit(): BelongsTo
{
return $this->belongsTo(Unit::class);
}
public function warehouse(): BelongsTo
{
return $this->belongsTo(Warehouse::class);
}
}

View File

@ -3,6 +3,7 @@
namespace App\Observers;
use App\Models\DelayedGood;
use App\Models\WarehouseStock;
class DelayedGoodObserver
{
@ -21,4 +22,59 @@ public function saving(DelayedGood $delayedGood): void
$delayedGood->payment_date = null;
}
}
/**
* Handle the DelayedGood "created" event.
*/
public function created(DelayedGood $delayedGood): void
{
if ($delayedGood->warehouse_id) {
WarehouseStock::adjustStock(
$delayedGood->warehouse_id,
$delayedGood->unit_id,
false,
-$delayedGood->quantity
);
}
}
/**
* Handle the DelayedGood "updated" event.
*/
public function updated(DelayedGood $delayedGood): void
{
if ($delayedGood->isDirty(['warehouse_id', 'unit_id', 'quantity'])) {
$oldWarehouseId = $delayedGood->getOriginal('warehouse_id');
$oldUnitId = $delayedGood->getOriginal('unit_id');
$oldQuantity = $delayedGood->getOriginal('quantity');
if ($oldWarehouseId) {
WarehouseStock::adjustStock($oldWarehouseId, $oldUnitId, false, $oldQuantity);
}
if ($delayedGood->warehouse_id) {
WarehouseStock::adjustStock($delayedGood->warehouse_id, $delayedGood->unit_id, false, -$delayedGood->quantity);
}
}
}
/**
* Handle the DelayedGood "deleted" event.
*/
public function deleted(DelayedGood $delayedGood): void
{
if (! $delayedGood->isForceDeleting() && $delayedGood->warehouse_id) {
WarehouseStock::adjustStock($delayedGood->warehouse_id, $delayedGood->unit_id, false, $delayedGood->quantity);
}
}
/**
* Handle the DelayedGood "restored" event.
*/
public function restored(DelayedGood $delayedGood): void
{
if ($delayedGood->warehouse_id) {
WarehouseStock::adjustStock($delayedGood->warehouse_id, $delayedGood->unit_id, false, -$delayedGood->quantity);
}
}
}

View File

@ -14,8 +14,9 @@ public function up(): void
Schema::create('delayed_goods', function (Blueprint $table) {
$table->id();
$table->foreignId('customer_id')->nullable()->constrained()->cascadeOnDelete();
$table->foreignId('warehouse_id')->nullable()->constrained()->nullOnDelete();
$table->foreignId('unit_id')->constrained()->cascadeOnDelete();
$table->unsignedInteger('quantity');
$table->decimal('quantity', 12, 2);
$table->unsignedInteger('unit_price');
$table->unsignedInteger('total_amount');
$table->unsignedInteger('paid_amount')->default(0);