From 5d39f002f1ee8c5704db364d929172d822a79db7 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 18 Dec 2025 11:08:53 +0700 Subject: [PATCH] feat: Implement stock activity logging when outlets are detached from items and add a DELETED status to AuditStockStatus. --- app/Enums/AuditStockStatus.php | 5 ++- .../Forms/Studio/Catalog/BottleForm.php | 37 +++++++++++++++++++ .../Forms/Studio/Catalog/PerfumeForm.php | 37 +++++++++++++++++++ .../Forms/Studio/Catalog/ProductForm.php | 37 +++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) diff --git a/app/Enums/AuditStockStatus.php b/app/Enums/AuditStockStatus.php index 25ed67c..f9f8f5a 100644 --- a/app/Enums/AuditStockStatus.php +++ b/app/Enums/AuditStockStatus.php @@ -12,6 +12,7 @@ enum AuditStockStatus: string case INCREASED = 'Menambah'; case DECREASED = 'Mengurangi'; case UPDATED = 'Mengubah'; + case DELETED = 'Menghapus'; public function label(): string { @@ -19,6 +20,7 @@ public function label(): string self::INCREASED => 'Menambah', self::DECREASED => 'Mengurangi', self::UPDATED => 'Mengubah', + self::DELETED => 'Menghapus', }; } @@ -26,8 +28,9 @@ public function color(): string { return match ($this) { self::INCREASED => 'emerald', - self::DECREASED => 'red', + self::DECREASED => 'orange', self::UPDATED => 'yellow', + self::DELETED => 'red', }; } } diff --git a/app/Livewire/Forms/Studio/Catalog/BottleForm.php b/app/Livewire/Forms/Studio/Catalog/BottleForm.php index 0e6437f..3f7558e 100644 --- a/app/Livewire/Forms/Studio/Catalog/BottleForm.php +++ b/app/Livewire/Forms/Studio/Catalog/BottleForm.php @@ -3,7 +3,9 @@ namespace App\Livewire\Forms\Studio\Catalog; use App\Models\Bottle; +use App\Models\Outlet; use App\Rules\UnsignedInteger; +use App\Services\StockActivityLogService; use App\Traits\Media\WithMediaHandler; use Illuminate\Support\Facades\DB; use Illuminate\Validation\Rule; @@ -90,8 +92,43 @@ public function update(): void DB::transaction(function () { $this->bottle->update($this->prepareSavedData()); + // Get old outlet IDs before sync + $oldOutlets = $this->bottle->outlets() + ->withPivot('stock') + ->get() + ->keyBy('id'); + + $oldOutletIds = $oldOutlets->keys()->toArray(); + + // Sync outlets $this->bottle->outlets()->sync($this->outlet_ids); + // Outlet yang ter-detach + $detachedOutletIds = array_diff($oldOutletIds, $this->outlet_ids); + + foreach ($detachedOutletIds as $outletId) { + $outlet = $oldOutlets[$outletId]; + $previousStock = $outlet->pivot->stock ?? 0; + + if ($previousStock > 0) { + StockActivityLogService::log( + logName: 'Update Outlet', + event: 'Menghapus', + description: 'Outlet '.$outlet->name.' dihapus dari bottle '.$this->bottle->name, + performedOn: $this->bottle, + outlet: $outlet, + quantityChange: $previousStock, + previousStock: $previousStock, + newStock: 0, + extraProperties: [ + 'action' => 'detach_outlet', + 'item_type' => 'bottle', + 'item_id' => $this->bottle->id, + ] + ); + } + } + $this->syncMedia($this->image, $this->bottle, 'image'); $this->uploadMedia($this->image, $this->bottle, 'image'); }); diff --git a/app/Livewire/Forms/Studio/Catalog/PerfumeForm.php b/app/Livewire/Forms/Studio/Catalog/PerfumeForm.php index 705ff73..c33a5bd 100644 --- a/app/Livewire/Forms/Studio/Catalog/PerfumeForm.php +++ b/app/Livewire/Forms/Studio/Catalog/PerfumeForm.php @@ -3,8 +3,10 @@ namespace App\Livewire\Forms\Studio\Catalog; use App\Enums\Concentration; +use App\Models\Outlet; use App\Models\Perfume; use App\Rules\UnsignedInteger; +use App\Services\StockActivityLogService; use App\Traits\Media\WithMediaHandler; use Illuminate\Support\Facades\DB; use Illuminate\Validation\Rule; @@ -133,8 +135,43 @@ public function update(): void $this->perfume->categories()->sync($this->category_ids); + // Get old outlet IDs before sync + $oldOutlets = $this->perfume->outlets() + ->withPivot('stock') + ->get() + ->keyBy('id'); + + $oldOutletIds = $oldOutlets->keys()->toArray(); + + // Sync outlets $this->perfume->outlets()->sync($this->outlet_ids); + // Outlet yang ter-detach + $detachedOutletIds = array_diff($oldOutletIds, $this->outlet_ids); + + foreach ($detachedOutletIds as $outletId) { + $outlet = $oldOutlets[$outletId]; + $previousStock = $outlet->pivot->stock ?? 0; + + if ($previousStock > 0) { + StockActivityLogService::log( + logName: 'Update Outlet', + event: 'Menghapus', + description: 'Outlet '.$outlet->name.' dihapus dari perfume '.$this->perfume->name, + performedOn: $this->perfume, + outlet: $outlet, + quantityChange: $previousStock, + previousStock: $previousStock, + newStock: 0, + extraProperties: [ + 'action' => 'detach_outlet', + 'item_type' => 'perfume', + 'item_id' => $this->perfume->id, + ] + ); + } + } + $this->syncMedia($data['image'], $this->perfume, 'image'); $this->uploadMedia($data['image'], $this->perfume, 'image'); }); diff --git a/app/Livewire/Forms/Studio/Catalog/ProductForm.php b/app/Livewire/Forms/Studio/Catalog/ProductForm.php index 08e6ab3..f383b7d 100644 --- a/app/Livewire/Forms/Studio/Catalog/ProductForm.php +++ b/app/Livewire/Forms/Studio/Catalog/ProductForm.php @@ -2,8 +2,10 @@ namespace App\Livewire\Forms\Studio\Catalog; +use App\Models\Outlet; use App\Models\Product; use App\Rules\UnsignedInteger; +use App\Services\StockActivityLogService; use App\Traits\Media\WithMediaHandler; use Illuminate\Support\Facades\DB; use Illuminate\Validation\Rule; @@ -100,8 +102,43 @@ public function update(): void DB::transaction(function () use ($data) { $this->product->update($data); + // Get old outlet IDs before sync + $oldOutlets = $this->product->outlets() + ->withPivot('stock') + ->get() + ->keyBy('id'); + + $oldOutletIds = $oldOutlets->keys()->toArray(); + + // Sync outlets $this->product->outlets()->sync($this->outlet_ids); + // Outlet yang ter-detach + $detachedOutletIds = array_diff($oldOutletIds, $this->outlet_ids); + + foreach ($detachedOutletIds as $outletId) { + $outlet = $oldOutlets[$outletId]; + $previousStock = $outlet->pivot->stock ?? 0; + + if ($previousStock > 0) { + StockActivityLogService::log( + logName: 'Update Outlet', + event: 'Menghapus', + description: 'Outlet '.$outlet->name.' dihapus dari product '.$this->product->name, + performedOn: $this->product, + outlet: $outlet, + quantityChange: $previousStock, + previousStock: $previousStock, + newStock: 0, + extraProperties: [ + 'action' => 'detach_outlet', + 'item_type' => 'product', + 'item_id' => $this->product->id, + ] + ); + } + } + $this->syncMedia($data['image'], $this->product, 'image'); $this->uploadMedia($data['image'], $this->product, 'image'); });