|null */ public function getTodayAttendanceForUser(User $user): ?array { $employee = $user->employee; if ($employee === null) { return null; } $attendance = Attendance::query() ->with('media') ->where('employee_id', $employee->id) ->whereDate('attendance_date', today()) ->first(); return $attendance?->toArray(); } public function isOnLeaveTodayForUser(User $user): bool { $employee = $user->employee; if ($employee === null) { return false; } return LeaveRequest::query() ->approved() ->where('employee_id', $employee->id) ->whereDate('start_date', '<=', today()) ->whereDate('end_date', '>=', today()) ->exists(); } public function canCheckInForUser(User $user): bool { return $user->can('attendances.create') && $user->employee !== null; } public function getAttendance(): array { $totalEmployees = Employee::query()->count(); $today = Carbon::today(); $present = Attendance::query() ->where('attendance_date', $today) ->distinct('employee_id') ->count('employee_id'); $onLeave = LeaveRequest::query() ->approved() ->where('start_date', '<=', $today) ->where('end_date', '>=', $today) ->distinct('employee_id') ->count('employee_id'); $absent = max(0, $totalEmployees - $present - $onLeave); return [ 'total_employees' => $totalEmployees, 'percentage' => $totalEmployees > 0 ? round($present / $totalEmployees * 100) : 0, 'present' => $present, 'absent' => $absent, 'on_leave' => $onLeave, ]; } public function getCashOverview(): array { $totalBalance = CashAccount::query()->sum('balance'); $summary = CashTransaction::query() ->whereDate('created_at', Carbon::today()) ->selectRaw(" COUNT(*) as total_transactions, COALESCE(SUM(CASE WHEN type = 'deposit' THEN amount ELSE 0 END), 0) as total_deposit, COALESCE(SUM(CASE WHEN type = 'withdrawal' THEN amount ELSE 0 END), 0) as total_withdrawal ") ->first(); return [ 'total_balance' => (int) $totalBalance, 'total_transactions' => (int) ($summary->total_transactions ?? 0), 'total_deposit' => (int) ($summary->total_deposit ?? 0), 'total_withdrawal' => (int) ($summary->total_withdrawal ?? 0), ]; } public function getRevenueSummary(): array { $revenueSummary = Order::query() ->completed() ->whereDate('created_at', Carbon::today()) ->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, SUM(shipping_cost) as total_shipping, COUNT(*) as total_orders, AVG(total_amount) as avg_order') ->first(); $totalMarketplaceFees = Order::query() ->completed() ->whereNotNull('marketplace_settings_snapshot') ->whereDate('created_at', Carbon::today()) ->get() ->sum(fn ($order) => (int) ($order->marketplace_settings_snapshot['total_fee_amount'] ?? 0)); return [ 'total_revenue' => (int) ($revenueSummary->total_revenue ?? 0), 'total_discount' => (int) ($revenueSummary->total_discount ?? 0), 'total_marketplace_fees' => $totalMarketplaceFees, 'total_potongan' => (int) ($revenueSummary->total_discount ?? 0) + $totalMarketplaceFees, 'total_shipping' => (int) ($revenueSummary->total_shipping ?? 0), 'total_orders' => (int) ($revenueSummary->total_orders ?? 0), 'avg_order' => (int) ($revenueSummary->avg_order ?? 0), ]; } public function getExpenseSummary(): array { $today = Carbon::today(); $purchase = Purchase::query() ->whereDate('created_at', $today) ->selectRaw('COALESCE(SUM(total), 0) as total') ->first(); $expenses = Expense::query() ->whereDate('created_at', $today) ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); $employeeAdvance = EmployeeAdvance::query() ->whereDate('created_at', $today) ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); $purchaseTotal = (int) ($purchase->total ?? 0); $expenseTotal = (int) ($expenses->total ?? 0); $advanceTotal = (int) ($employeeAdvance->total ?? 0); return [ 'total' => $purchaseTotal + $expenseTotal + $advanceTotal, 'purchase_total' => $purchaseTotal, 'expense_total' => $expenseTotal, 'advance_total' => $advanceTotal, ]; } public function getOrderStats(): array { $byChannel = Order::query() ->whereDate('created_at', Carbon::today()) ->selectRaw('channel, COUNT(*) as count, SUM(total_amount) as total') ->groupBy('channel') ->get() ->map(fn ($item) => [ 'channel' => $item->channel instanceof OrderChannel ? $item->channel->value : $item->channel, 'label' => $item->channel instanceof OrderChannel ? $item->channel->label() : OrderChannel::from($item->channel)->label(), 'count' => (int) $item->count, 'total' => (int) $item->total, ]); $byPaymentType = Order::query() ->whereDate('created_at', Carbon::today()) ->selectRaw('payment_type, COUNT(*) as count, SUM(total_amount) as total') ->groupBy('payment_type') ->get() ->map(fn ($item) => [ 'payment_type' => $item->payment_type instanceof PaymentType ? $item->payment_type->value : $item->payment_type, 'label' => $item->payment_type instanceof PaymentType ? $item->payment_type->label() : PaymentType::from($item->payment_type)->label(), 'count' => (int) $item->count, 'total' => (int) $item->total, ]); $byMarketing = Order::query() ->whereNotNull('marketing_id') ->whereDate('orders.created_at', Carbon::today()) ->join('users', 'orders.marketing_id', '=', 'users.id') ->leftJoin('user_profiles', 'users.id', '=', 'user_profiles.user_id') ->selectRaw('COALESCE(user_profiles.full_name, users.username) as name, COUNT(*) as count, SUM(orders.total_amount) as total') ->groupBy('orders.marketing_id', 'users.username', 'user_profiles.full_name') ->orderByDesc('total') ->limit(5) ->get() ->map(fn ($item) => [ 'name' => $item->name, 'count' => (int) $item->count, 'total' => (int) $item->total, ]); $byStatus = Order::query() ->whereDate('created_at', Carbon::today()) ->selectRaw('status, COUNT(*) as count') ->groupBy('status') ->get() ->map(fn ($item) => [ 'status' => $item->status instanceof OrderStatus ? $item->status->value : $item->status, 'label' => $item->status instanceof OrderStatus ? $item->status->label() : OrderStatus::from($item->status)->label(), 'count' => (int) $item->count, ]); return [ 'by_channel' => $byChannel->toArray(), 'by_payment_type' => $byPaymentType->toArray(), 'by_marketing' => $byMarketing->toArray(), 'by_status' => $byStatus->toArray(), ]; } }