From 64776845407b23967d06309a480ac7e5d10264aa Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 12 Feb 2026 14:27:40 +0700 Subject: [PATCH] feat: add stock adjustment functionality for warehouse items via a modal form. --- .../Master/Warehouse/AdjustmentStockForm.php | 97 +++++++++++++++++++ app/Livewire/Studio/Master/Warehouse/Show.php | 39 +++++++- .../studio/master/warehouse/show.blade.php | 76 ++++++++++++--- 3 files changed, 198 insertions(+), 14 deletions(-) create mode 100644 app/Livewire/Forms/Studio/Master/Warehouse/AdjustmentStockForm.php diff --git a/app/Livewire/Forms/Studio/Master/Warehouse/AdjustmentStockForm.php b/app/Livewire/Forms/Studio/Master/Warehouse/AdjustmentStockForm.php new file mode 100644 index 0000000..24e346e --- /dev/null +++ b/app/Livewire/Forms/Studio/Master/Warehouse/AdjustmentStockForm.php @@ -0,0 +1,97 @@ + 'required', + 'note' => 'nullable', + ]; + } + + public function validationAttributes(): array + { + return [ + 'newStock' => 'stok baru', + 'note' => 'keterangan', + ]; + } + + public function setAdjustment(string $itemId, string $type, string $name, int $stock): void + { + $this->itemId = $itemId; + $this->type = $type; + $this->name = $name; + $this->oldStock = formatCurrencyNumber($stock); + $this->newStock = formatCurrencyNumber($stock); + $this->note = null; + } + + public function save(Warehouse $warehouse): void + { + $this->validate(); + + $newStockValue = (int) str_replace(['.', ','], '', (string) $this->newStock); + $oldStockValue = (int) str_replace(['.', ','], '', (string) $this->oldStock); + + $typeId = explode('_', $this->itemId); + $type = $typeId[0]; + $id = $typeId[1]; + + $relation = match ($type) { + 'perfume' => 'perfumes', + 'product' => 'products', + 'bottle' => 'bottles', + default => null, + }; + + if (! $relation) { + return; + } + + $item = $warehouse->{$relation}()->find($id); + + if (! $item) { + return; + } + + $warehouse->{$relation}()->updateExistingPivot($id, [ + 'stock' => $newStockValue, + ]); + + // Log the activity + StockActivityLogService::logWarehouse( + logName: 'adjustment', + event: 'update', + description: "Manual adjustment for {$this->name}: changed from {$oldStockValue} to {$newStockValue}. Note: ".($this->note ?? '-'), + performedOn: $item, + warehouse: $warehouse, + quantityChange: $newStockValue - $oldStockValue, + previousStock: $oldStockValue, + newStock: $newStockValue, + extraProperties: [ + 'note' => $this->note, + 'adjustment_type' => 'manual', + ] + ); + } +} diff --git a/app/Livewire/Studio/Master/Warehouse/Show.php b/app/Livewire/Studio/Master/Warehouse/Show.php index f4496b1..16de847 100644 --- a/app/Livewire/Studio/Master/Warehouse/Show.php +++ b/app/Livewire/Studio/Master/Warehouse/Show.php @@ -2,16 +2,26 @@ namespace App\Livewire\Studio\Master\Warehouse; +use App\Livewire\Forms\Studio\Master\Warehouse\AdjustmentStockForm; use App\Models\Warehouse; use App\Traits\Authorization\WithAuthorization; +use App\Traits\Components\WithCloseModal; +use App\Traits\Components\WithConfirmation; +use App\Traits\Components\WithToast; +use App\Traits\Notification\WithSubscribeNotification; +use App\Traits\Utilities\WithUpdatedData; +use Flux\Flux; use Illuminate\Contracts\View\View; +use Livewire\Attributes\On; use Livewire\Attributes\Title; use Livewire\Component; #[Title('Detail Gudang')] class Show extends Component { - use WithAuthorization; + use WithAuthorization, WithCloseModal, WithConfirmation, WithSubscribeNotification, WithToast, WithUpdatedData; + + public AdjustmentStockForm $form; public Warehouse $warehouse; @@ -19,6 +29,10 @@ class Show extends Component public array $type = []; + public string $method = 'saveAdjustment'; + + public string $modalTitle = ''; + public function mount(Warehouse $warehouse): void { $this->warehouse = $warehouse; @@ -121,6 +135,29 @@ public function getItemsProperty() return $perfumes->concat($products)->concat($bottles); } + #[On('modal:open')] + public function openModal(string $method, string $modalTitle, string $itemId, string $type, string $name, int $stock): void + { + $this->resetValidation(); + $this->resetErrorBag(); + + $this->method = $method; + $this->modalTitle = $modalTitle; + + $this->form->setAdjustment($itemId, $type, $name, $stock); + } + + public function saveAdjustment(): void + { + $this->canOrAbort('manage adjustment'); + + $this->form->save($this->warehouse); + + $this->toast('Stok berhasil diperbarui.'); + + Flux::modals()->close(); + } + public function render(): View { return view('livewire.studio.master.warehouse.show', [ diff --git a/resources/views/livewire/studio/master/warehouse/show.blade.php b/resources/views/livewire/studio/master/warehouse/show.blade.php index f1e2ccc..da01e53 100644 --- a/resources/views/livewire/studio/master/warehouse/show.blade.php +++ b/resources/views/livewire/studio/master/warehouse/show.blade.php @@ -46,9 +46,9 @@ Tipe Item Stok - @can('audit stock warehouse') + @canAny(['manage adjustment', 'audit stock warehouse']) Aksi - @endcan + @endcanAny @@ -57,22 +57,35 @@ {{ $item['type'] }} {{ $item['name'] }} {{ number_format($item['stock'], 0, ',', '.') }} - - @can('audit stock warehouse') - - - - - @endcan - + @canAny(['manage adjustment', 'audit stock warehouse']) + + @can('audit stock warehouse') + + + + + @endcan + @can('manage adjustment') + + + + + + + @endcan + + @endcanAny @empty @@ -85,4 +98,41 @@ + + +
+
+ {{ $modalTitle }} + Sesuaikan stok untuk {{ $form?->name ?? '-' }} ({{ $form?->type ?? '-' }}) + +
+ +
+ + Stok Saat Ini + + + + + Stok Baru * + + + +
+ + + Keterangan + + + + +
+ + + Simpan + +
+
+