parfum/app/Livewire/Studio/Manage/StockOpname/Index.php

133 lines
4.0 KiB
PHP

<?php
namespace App\Livewire\Studio\Manage\StockOpname;
use App\Enums\StockOpnameStatus;
use App\Models\StockOpname;
use App\Services\StockActivityLogService;
use App\Traits\Components\WithConfirmation;
use App\Traits\Components\WithToast;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Title;
use Livewire\Component;
#[Title('Stock Opname')]
class Index extends Component
{
use WithConfirmation, WithToast;
public $stockOpname;
public function mount(): void
{
$this->loadItems();
}
protected function loadItems(): void
{
$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 = formatDateLocalized($stockOpname->period_month, 'F Y');
return $stockOpname;
});
}
public function requestApproval(StockOpname $stockOpname): void
{
$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): void
{
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;
if (! $itemable) {
continue;
}
$morphType = class_basename($itemable);
$relationMap = [
'Perfume' => 'perfumes',
'Product' => 'products',
'Bottle' => 'bottles',
];
if (! isset($relationMap[$morphType])) {
continue;
}
$relationName = $relationMap[$morphType];
$currentPivot = $outlet->$relationName()
->where($itemable->getTable().'.id', $itemable->id)
->first();
$currentStock = $currentPivot?->pivot?->stock ?? 0;
$quantity = $item->qty_physical;
$outlet->$relationName()->syncWithoutDetaching([
$itemable->id => ['stock' => $quantity],
]);
StockActivityLogService::stockOpname(
stockOpname: $stockOpname,
product: $itemable,
quantityChange: $quantity - $currentStock,
previousStock: $currentStock,
newStock: $quantity,
note: $stockOpname->note
);
}
});
$this->toast('Stock opname berhasil disetujui dan stok outlet disesuaikan.', 'Berhasil');
$this->redirectRoute('studio.manage.stock_opname.index', navigate: true);
}
public function render(): View
{
return view('livewire.studio.manage.stock-opname.index', [
'pageTitle' => 'Stock Opname',
]);
}
}