232 lines
9.3 KiB
PHP
232 lines
9.3 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Studio\Dashboard;
|
|
|
|
use App\Models\Expense;
|
|
use App\Models\Order;
|
|
use App\Models\OrderItem;
|
|
use App\Models\Perfume;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Livewire\Attributes\Title;
|
|
use Livewire\Component;
|
|
|
|
#[Title('Ringkasan')]
|
|
class Overview extends Component
|
|
{
|
|
public array $outlets = [];
|
|
|
|
public array $selectedOutletIds = [];
|
|
|
|
public array $stats = [];
|
|
|
|
public function mount()
|
|
{
|
|
$this->outlets = auth()->user()->outlets()->get()->pluck('name', 'id')->toArray();
|
|
|
|
$this->loadStats();
|
|
}
|
|
|
|
public function updatedSelectedOutletIds()
|
|
{
|
|
$this->loadStats();
|
|
}
|
|
|
|
protected function loadStats()
|
|
{
|
|
$outletIds = $this->selectedOutletIds;
|
|
|
|
$todayOrder = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->today()
|
|
->count();
|
|
|
|
$yesterdayOrder = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->yesterday()
|
|
->count();
|
|
|
|
$todayIncome = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->today()
|
|
->sum('total');
|
|
|
|
$yesterdayIncome = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->yesterday()
|
|
->sum('total');
|
|
|
|
$todayCogs = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->today()
|
|
->sum('cogs');
|
|
|
|
$yesterdayCogs = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->yesterday()
|
|
->sum('cogs');
|
|
|
|
$todayDiscount = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->today()
|
|
->sum('discount');
|
|
|
|
$yesterdayDiscount = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->yesterday()
|
|
->sum('discount');
|
|
|
|
$todayVoucher = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->today()
|
|
->whereNotNull('voucher_id')
|
|
->count();
|
|
|
|
$yesterdayVoucher = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->yesterday()
|
|
->whereNotNull('voucher_id')
|
|
->count();
|
|
|
|
$todayExpense = Expense::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->today()
|
|
->sum('amount');
|
|
|
|
$yesterdayExpense = Expense::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
|
|
->yesterday()
|
|
->sum('amount');
|
|
|
|
$todayGrossProfit = $todayIncome - $todayCogs - $todayDiscount;
|
|
$yesterdayGrossProfit = $yesterdayIncome - $yesterdayCogs - $yesterdayDiscount;
|
|
|
|
$todayNetProfit = $todayGrossProfit - $todayExpense;
|
|
$yesterdayNetProfit = $yesterdayGrossProfit - $yesterdayExpense;
|
|
|
|
$todaySoldPerfume = OrderItem::where('orderable_type', Perfume::class)
|
|
->whereHas(
|
|
'order',
|
|
fn ($q) => $q->today()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))
|
|
)
|
|
->sum('quantity');
|
|
|
|
$yesterdaySoldPerfume = OrderItem::where('orderable_type', Perfume::class)
|
|
->whereHas(
|
|
'order',
|
|
fn ($q) => $q->yesterday()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))
|
|
)
|
|
->sum('quantity');
|
|
|
|
$todayTopPerfume = OrderItem::where('orderable_type', Perfume::class)
|
|
->whereHas(
|
|
'order',
|
|
fn ($q) => $q->today()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))
|
|
)
|
|
->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold'))
|
|
->groupBy('orderable_id', 'orderable_type')
|
|
->orderByDesc('total_sold')
|
|
->with('orderable')
|
|
->first();
|
|
|
|
$yesterdayTopPerfume = OrderItem::where('orderable_type', Perfume::class)
|
|
->whereHas(
|
|
'order',
|
|
fn ($q) => $q->yesterday()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))
|
|
)
|
|
->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold'))
|
|
->groupBy('orderable_id', 'orderable_type')
|
|
->orderByDesc('total_sold')
|
|
->with('orderable')
|
|
->first();
|
|
|
|
$this->stats = [
|
|
[
|
|
'title' => 'Total Order',
|
|
'value' => $todayOrder,
|
|
'previous' => $yesterdayOrder,
|
|
'trend' => $yesterdayOrder > 0
|
|
? round((($todayOrder - $yesterdayOrder) / $yesterdayOrder) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayOrder > $yesterdayOrder,
|
|
],
|
|
[
|
|
'title' => 'Pendapatan',
|
|
'value' => currency($todayIncome, 'Rp'),
|
|
'previous' => currency($yesterdayIncome, 'Rp'),
|
|
'trend' => $yesterdayIncome > 0
|
|
? round((($todayIncome - $yesterdayIncome) / $yesterdayIncome) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayIncome > $yesterdayIncome,
|
|
'formatted' => currency($todayIncome, 'Rp'),
|
|
],
|
|
[
|
|
'title' => 'HPP',
|
|
'value' => currency($todayCogs, 'Rp'),
|
|
'previous' => currency($yesterdayCogs, 'Rp'),
|
|
'trend' => $yesterdayCogs > 0
|
|
? round((($todayCogs - $yesterdayCogs) / $yesterdayCogs) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayCogs > $yesterdayCogs,
|
|
'formatted' => currency($todayCogs, 'Rp'),
|
|
],
|
|
[
|
|
'title' => 'Diskon',
|
|
'value' => currency($todayDiscount, 'Rp'),
|
|
'previous' => currency($yesterdayDiscount, 'Rp'),
|
|
'trend' => $yesterdayDiscount > 0
|
|
? round((($todayDiscount - $yesterdayDiscount) / $yesterdayDiscount) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayDiscount > $yesterdayDiscount,
|
|
'formatted' => currency($todayDiscount, 'Rp'),
|
|
],
|
|
[
|
|
'title' => 'Voucher Terpakai',
|
|
'value' => $todayVoucher,
|
|
'previous' => $yesterdayVoucher,
|
|
'trend' => $yesterdayVoucher > 0
|
|
? round((($todayVoucher - $yesterdayVoucher) / $yesterdayVoucher) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayVoucher > $yesterdayVoucher,
|
|
],
|
|
[
|
|
'title' => 'Pengeluaran',
|
|
'value' => currency($todayExpense, 'Rp'),
|
|
'previous' => currency($yesterdayExpense, 'Rp'),
|
|
'trend' => $yesterdayExpense > 0
|
|
? round((($todayExpense - $yesterdayExpense) / $yesterdayExpense) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayExpense > $yesterdayExpense,
|
|
],
|
|
[
|
|
'title' => 'Laba Kotor',
|
|
'value' => currency($todayGrossProfit, 'Rp'),
|
|
'previous' => currency($yesterdayGrossProfit, 'Rp'),
|
|
'trend' => $yesterdayGrossProfit > 0
|
|
? round((($todayGrossProfit - $yesterdayGrossProfit) / $yesterdayGrossProfit) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayGrossProfit > $yesterdayGrossProfit,
|
|
],
|
|
[
|
|
'title' => 'Laba Bersih',
|
|
'value' => currency($todayNetProfit, 'Rp'),
|
|
'previous' => currency($yesterdayNetProfit, 'Rp'),
|
|
'trend' => $yesterdayNetProfit > 0
|
|
? round((($todayNetProfit - $yesterdayNetProfit) / $yesterdayNetProfit) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todayNetProfit > $yesterdayNetProfit,
|
|
],
|
|
[
|
|
'title' => 'Parfum Terjual',
|
|
'value' => $todaySoldPerfume.' ml',
|
|
'previous' => $yesterdaySoldPerfume.' ml',
|
|
'trend' => $yesterdaySoldPerfume > 0
|
|
? round((($todaySoldPerfume - $yesterdaySoldPerfume) / $yesterdaySoldPerfume) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => $todaySoldPerfume > $yesterdaySoldPerfume,
|
|
],
|
|
[
|
|
'title' => 'Top Parfum',
|
|
'value' => optional($todayTopPerfume?->orderable)->name.' ('.$todayTopPerfume?->total_sold.'ml)' ?? '-',
|
|
'previous' => optional($yesterdayTopPerfume?->orderable)->name.'('.$yesterdayTopPerfume?->total_sold.'ml)' ?? '-',
|
|
'trend' => ($yesterdayTopPerfume && $yesterdayTopPerfume->total_sold > 0)
|
|
? round((($todayTopPerfume?->total_sold - $yesterdayTopPerfume?->total_sold) / $yesterdayTopPerfume?->total_sold) * 100, 1).'%'
|
|
: '∞%',
|
|
'trendUp' => ($todayTopPerfume?->total_sold ?? 0) > ($yesterdayTopPerfume?->total_sold ?? 0),
|
|
],
|
|
];
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.studio.dashboard.overview');
|
|
}
|
|
}
|