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->selectedOutletIds = []; $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(), ], ]; $orderQuery = Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) ->when($dateQuery || ($startDate && $endDate), $filterDate); $totalIncome = (clone $orderQuery)->sum('total'); $totalCogs = (clone $orderQuery)->sum('cogs'); $totalDiscount = (clone $orderQuery)->sum('discount'); $expenseQuery = Expense::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) ->when($dateQuery || ($startDate && $endDate), $filterDate); $totalExpense = $expenseQuery->sum('amount'); $payrollQuery = Payroll::when(! empty($outletIds), fn ($q) => $q->whereHas('user.outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds))) ->when($dateQuery || ($startDate && $endDate), $filterDate) ->paid(); $totalPayroll = $payrollQuery->sum('total_salary'); $grossProfit = $totalIncome - $totalCogs - $totalDiscount; $netProfit = $grossProfit - $totalExpense - $totalPayroll; $this->orders = array_filter([ [ 'title' => 'Total Order', 'value' => formatCurrencyNumber( (clone $orderQuery)->count() ), ], [ 'title' => 'Pendapatan', 'value' => formatCurrencyNumber($totalIncome, 'Rp'), ], auth()->user()->hasRole(['Developer', 'Owner']) ? [ 'title' => 'HPP', 'value' => formatCurrencyNumber($totalCogs, 'Rp'), ] : null, auth()->user()->hasRole(['Developer', 'Owner']) ? [ 'title' => 'Laba Kotor', 'value' => formatCurrencyNumber($grossProfit, 'Rp'), ] : null, auth()->user()->hasRole(['Developer', 'Owner']) ? [ 'title' => 'Laba Bersih', 'value' => formatCurrencyNumber($netProfit, 'Rp'), ] : null, [ 'title' => 'Diskon', 'value' => formatCurrencyNumber($totalDiscount, 'Rp'), ], [ 'title' => 'Voucher Terpakai', 'value' => formatCurrencyNumber( (clone $orderQuery)->whereNotNull('voucher_id')->count() ), ], [ 'title' => 'Parfum Terjual', 'value' => formatCurrencyNumber( 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' => formatCurrencyNumber( 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' => formatCurrencyNumber( 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' => formatCurrencyNumber( Expense::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) ->when($dateQuery || ($startDate && $endDate), $filterDate) ->sum('amount'), 'Rp' ), ], auth()->user()->hasRole(['Developer', 'Owner']) ? [ 'title' => 'Belanja Barang', 'value' => formatCurrencyNumber( Purchase::when($dateQuery || ($startDate && $endDate), $filterDate) ->sum('total'), 'Rp' ), ] : null, [ 'title' => 'Penggajian', 'value' => formatCurrencyNumber( 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 = OrderItem::where('orderable_type', Perfume::class) ->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); }) ->with('orderable') ->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold'), DB::raw('SUM(unit_price * quantity) as total_sales_value')) ->groupBy('orderable_id', 'orderable_type') ->orderByDesc('total_sales_value') ->take(5) ->get() ->map(fn ($item) => [ 'name' => $item->orderable?->name ?? 'Unknown', 'sale_price' => formatCurrencyNumber($item->orderable?->sale_price ?? 0, 'Rp'), 'total_sold' => formatCurrencyNumber($item->total_sold), 'total_sales' => formatCurrencyNumber($item->total_sales_value, 'Rp'), ]) ->toArray(); $this->topProducts = OrderItem::where('orderable_type', Product::class) ->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); }) ->with('orderable') ->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold'), DB::raw('SUM(unit_price * quantity) as total_sales_value')) ->groupBy('orderable_id', 'orderable_type') ->orderByDesc('total_sales_value') ->take(5) ->get() ->map(fn ($item) => [ 'name' => $item->orderable?->name ?? 'Unknown', 'sale_price' => formatCurrencyNumber($item->orderable?->sale_price ?? 0, 'Rp'), 'total_sold' => formatCurrencyNumber($item->total_sold), 'total_sales' => formatCurrencyNumber($item->total_sales_value, 'Rp'), ]) ->toArray(); $this->topBottles = OrderItem::where('orderable_type', Bottle::class) ->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); }) ->with('orderable') ->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold'), DB::raw('SUM(unit_price * quantity) as total_sales_value')) ->groupBy('orderable_id', 'orderable_type') ->orderByDesc('total_sales_value') ->take(5) ->get() ->map(fn ($item) => [ 'name' => $item->orderable?->name ?? 'Unknown', 'sale_price' => formatCurrencyNumber($item->orderable?->sale_price ?? 0, 'Rp'), 'total_sold' => formatCurrencyNumber($item->total_sold), 'total_sales' => formatCurrencyNumber($item->total_sales_value, 'Rp'), ]) ->toArray(); } public function render() { return view('livewire.studio.dashboard.analysis', [ 'pageTitle' => 'Analisa', ]); } }