loadItems(); } protected function loadItems() { $this->stockOpname = StockOpname::with(['outlet', 'items']) ->where('period_month', now()->format('Y-m')) ->get() ->map(function ($stockOpname) { $outlet = $stockOpname->outlet; $parfumCount = $outlet->perfumes()->count(); $botolCount = $outlet->bottles()->count(); $produkCount = $outlet->products()->count(); $total = $parfumCount + $botolCount + $produkCount; $filled = $stockOpname->items() ->whereNotNull('qty_physical') ->count(); $percent = $total > 0 ? round(($filled / $total) * 100) : 0; $stockOpname->total_item = $total; $stockOpname->progress_filled = $filled; $stockOpname->progress_percent = $percent; $stockOpname->period_month = formatDate($stockOpname->period_month, 'F Y'); return $stockOpname; }); } public function requestApproval(StockOpname $stockOpname) { $stockOpname->update(['status' => StockOpnameStatus::PENDING_APPROVAL]); $this->toast('Permohonan persetujuan berhasil diajukan.', 'Berhasil'); $this->redirectRoute('studio.manage.stock_opname.index', navigate: true); } public function approveApproval(StockOpname $stockOpname) { DB::transaction(function () use ($stockOpname) { $stockOpname->update(['status' => StockOpnameStatus::COMPLETED]); $outlet = $stockOpname->outlet; foreach ($stockOpname->items as $item) { if (is_null($item->qty_physical)) { continue; } $itemable = $item->itemable; $morphType = class_basename($itemable); $relationMap = [ 'Perfume' => 'perfumes', 'Product' => 'products', 'Bottle' => 'bottles', ]; if (! isset($relationMap[$morphType])) { continue; } $relationName = $relationMap[$morphType]; $currentStock = $outlet->$relationName() ->where($itemable->getTable().'.id', $itemable->id) ->first()?->pivot?->stock ?? 0; $quantity = $item->qty_physical; $outlet->$relationName()->syncWithoutDetaching([ $itemable->id => ['stock' => $quantity], ]); activity('Stock Opname') ->performedOn($itemable) ->causedBy(auth()->user()) ->withProperties([ 'itemable_id' => $item->itemable_id, 'itemable_type' => $item->itemable_type, 'outlet_id' => $outlet->id, 'quantity_change' => $quantity, 'previous_stock' => $currentStock, 'new_stock' => $currentStock + $quantity, 'itemable_id' => $item->id ?? null, ]) ->event('Mengubah') ->log(sprintf( 'Stok %s di %s diperbarui dari %s menjadi %s', $itemable->name, $outlet->name, $currentStock, $quantity )); } }); $this->toast('Stock opname berhasil disetujui dan stok outlet disesuaikan.', 'Berhasil'); $this->redirectRoute('studio.manage.stock_opname.index', navigate: true); } public function render() { return view('livewire.studio.manage.stock-opname.index', [ 'pageTitle' => 'Stock Opname', ]); } }