parfum/app/Livewire/Studio/Dashboard/Analysis.php

342 lines
13 KiB
PHP

<?php
namespace App\Livewire\Studio\Dashboard;
use App\Models\Bottle;
use App\Models\Brand;
use App\Models\Category;
use App\Models\Customer;
use App\Models\Expense;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Outlet;
use App\Models\Payroll;
use App\Models\Perfume;
use App\Models\Product;
use App\Models\Purchase;
use App\Models\Tier;
use App\Models\User;
use App\Models\Voucher;
use App\Traits\Notification\WithSubscribeNotification;
use Carbon\Carbon;
use Livewire\Attributes\Title;
use Livewire\Component;
#[Title('Analisa')]
class Analysis extends Component
{
use WithSubscribeNotification;
public string $period = 'all';
public array $outlets = [];
public array $range = [
'start' => null,
'end' => null,
];
public array $selectedOutletIds = [];
public array $countingData = [];
public array $orders = [];
public array $expenses = [];
public array $topPerfumes = [];
public array $topProducts = [];
public array $topBottles = [];
public function mount()
{
$this->outlets = auth()->user()->outlets()->get()->pluck('name', 'id')->toArray();
$this->loadData();
}
public function updatedPeriod(string $period)
{
$this->loadData();
}
public function updatedSelectedOutletIds()
{
$this->loadData();
}
public function updatedRange($range)
{
$this->loadData();
}
protected function loadData()
{
$outletIds = $this->selectedOutletIds;
$period = $this->period;
$range = $this->range;
$dateQuery = match ($period) {
'7' => now()->subDays(1),
'30' => now()->subDays(30),
'90' => now()->subDays(90),
'365' => now()->subDays(365),
default => null,
};
$startDate = ! empty($range['start']) ? Carbon::parse($range['start'])->startOfDay() : null;
$endDate = ! empty($range['end']) ? Carbon::parse($range['end'])->endOfDay() : null;
if ($startDate && $endDate) {
$dateQuery = null;
}
$filterDate = function ($q) use ($dateQuery, $startDate, $endDate) {
if ($startDate && $endDate) {
$q->whereBetween('created_at', [$startDate, $endDate]);
} elseif ($dateQuery) {
$q->where('created_at', '>=', $dateQuery);
}
};
$this->countingData = [
[
'title' => 'Outlet',
'value' => Outlet::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
],
[
'title' => 'Pegawai',
'value' => User::whereHas('employee')
->when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->withoutDeveloper()
->count(),
],
[
'title' => 'Tier',
'value' => Tier::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
],
[
'title' => 'Voucher Aktif',
'value' => Voucher::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->active()
->count(),
],
[
'title' => 'Member',
'value' => User::whereHas('customer')
->when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->count(),
],
[
'title' => 'Customer',
'value' => Customer::whereDoesntHave('user')
->when($dateQuery || ($startDate && $endDate), $filterDate)
->count(),
],
[
'title' => 'Kategori',
'value' => Category::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
],
[
'title' => 'Merek',
'value' => Brand::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
],
[
'title' => 'Parfum',
'value' => Perfume::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->count(),
],
[
'title' => 'Produk',
'value' => Product::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->count(),
],
[
'title' => 'Botol',
'value' => Bottle::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->count(),
],
];
$this->orders = array_filter([
[
'title' => 'Total Order',
'value' => currency(
Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->count()
),
],
[
'title' => 'Pendapatan',
'value' => currency(
Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->sum('total'),
'Rp'
),
],
auth()->user()?->hasPermissionTo('view cogs') ? [
'title' => 'HPP',
'value' => currency(
Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->sum('cogs'),
'Rp'
),
] : null,
[
'title' => 'Diskon',
'value' => currency(
Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->sum('discount'),
'Rp'
),
],
[
'title' => 'Voucher Terpakai',
'value' => currency(
Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->whereNotNull('voucher_id')->count()
),
],
[
'title' => 'Parfum Terjual',
'value' => currency(
OrderItem::where('orderable_type', Perfume::class)
->whereHas('order', fn ($q) => $q->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))->when($dateQuery || ($startDate && $endDate), $filterDate))
->sum('quantity')
).' ml',
],
[
'title' => 'Produk Terjual',
'value' => currency(
OrderItem::where('orderable_type', Product::class)
->whereHas('order', fn ($q) => $q->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))->when($dateQuery || ($startDate && $endDate), $filterDate))
->sum('quantity')
).' pcs',
],
[
'title' => 'Botol Terjual',
'value' => currency(
OrderItem::where('orderable_type', Bottle::class)
->whereHas('order', fn ($q) => $q->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))->when($dateQuery || ($startDate && $endDate), $filterDate))
->sum('quantity')
).' pcs',
],
]);
$this->expenses = array_filter([
[
'title' => 'Beban Toko',
'value' => currency(
Expense::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->sum('amount'),
'Rp'
),
],
auth()->user()?->hasPermissionTo('view cogs') ? [
'title' => 'Belanja Barang',
'value' => currency(
Purchase::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->sum('total'),
'Rp'
),
] : null,
[
'title' => 'Penggajian',
'value' => currency(
Payroll::when(! empty($outletIds), fn ($q) => $q->whereHas('user.outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
->when($dateQuery || ($startDate && $endDate), $filterDate)
->paid()
->sum('total_salary'),
'Rp'
),
],
]);
$this->topPerfumes = Perfume::with(['items' => function ($query) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
$query->whereNotNull('order_id')
->whereHas('order', function ($q) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
$q->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate);
});
}])
->select('id', 'name', 'sale_price')
->get()
->map(fn ($perfume) => [
'name' => $perfume->name,
'sale_price' => currency($perfume->sale_price, 'Rp'),
'total_sold' => currency($perfume->items->sum('quantity')),
'total_sales' => currency($perfume->items->sum(fn ($item) => $item->order?->total ?? 0), 'Rp'),
])
->sortByDesc('total_sales')
->filter(fn ($product) => $product['total_sold'] > 0)
->take(5)
->toArray();
$this->topProducts = Product::with(['items' => function ($query) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
$query->whereNotNull('order_id')
->whereHas('order', function ($q) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
$q->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate);
});
}])
->select('id', 'name', 'sale_price')
->get()
->map(fn ($product) => [
'name' => $product->name,
'sale_price' => currency($product->sale_price, 'Rp'),
'total_sold' => currency($product->items->sum('quantity')),
'total_sales' => currency($product->items->sum(fn ($item) => $item->order?->total ?? 0), 'Rp'),
])
->sortByDesc('total_sales')
->filter(fn ($product) => $product['total_sold'] > 0)
->take(5)
->toArray();
$this->topBottles = Bottle::with(['items' => function ($query) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
$query->whereNotNull('order_id')
->whereHas('order', function ($q) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
$q->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
->when($dateQuery || ($startDate && $endDate), $filterDate);
});
}])
->select('id', 'name', 'sale_price')
->get()
->map(fn ($bottle) => [
'name' => $bottle->name,
'sale_price' => currency($bottle->sale_price, 'Rp'),
'total_sold' => currency($bottle->items->sum('quantity')),
'total_sales' => currency($bottle->items->sum(fn ($item) => $item->order?->total ?? 0), 'Rp'),
])
->sortByDesc('total_sales')
->filter(fn ($product) => $product['total_sold'] > 0)
->take(5)
->toArray();
}
public function render()
{
return view('livewire.studio.dashboard.analysis', [
'pageTitle' => 'Analisa',
]);
}
}