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 { /** @var User|null $user */ $user = auth()->user(); $isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false; $attendanceRoles = collect(Role::cases()) ->filter(fn (Role $role) => in_array(Permission::ATTENDANCES_VIEW, $role->permissions())) ->map(fn (Role $role) => $role->value) ->values() ->toArray(); $employeeQuery = Employee::query(); $attendanceQuery = Attendance::query()->where('attendance_date', Carbon::today()); $leaveRequestQuery = LeaveRequest::query() ->approved() ->where('start_date', '<=', Carbon::today()) ->where('end_date', '>=', Carbon::today()); if (! $isSuper) { $employeeId = $user?->employee?->id; $employeeQuery->where('id', $employeeId); $attendanceQuery->where('employee_id', $employeeId); $leaveRequestQuery->where('employee_id', $employeeId); } $employeeQuery->whereHas('user.roles', fn ($q) => $q->whereIn('name', $attendanceRoles)); $totalEmployees = $employeeQuery->count(); $present = $attendanceQuery->distinct('employee_id')->count('employee_id'); $onLeave = $leaveRequestQuery->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 { /** @var User|null $user */ $user = auth()->user(); $isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false; $totalBalanceQuery = CashAccount::query(); $transactionQuery = CashTransaction::query()->whereDate('created_at', Carbon::today()); if (! $isSuper) { $transactionQuery->where('created_by_id', $user->id); $totalBalanceQuery->whereHas('transactions', fn ($q) => $q->where('created_by_id', $user->id)); } $totalBalance = $totalBalanceQuery->sum('balance'); $summary = $transactionQuery ->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 { /** @var User|null $user */ $user = auth()->user(); $isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $revenueSummary = Order::query() ->completed() ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('created_by_id', $user->id)) ->whereDate('created_at', Carbon::today()) ->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, COUNT(*) as total_orders, AVG(total_amount) as avg_order') ->first(); $totalMarketplaceFees = Order::query() ->completed() ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('created_by_id', $user->id)) ->whereNotNull('marketplace_settings_snapshot') ->whereDate('created_at', Carbon::today()) ->get() ->sum(fn ($order) => (int) ($order->marketplace_settings_snapshot['total_fee_amount'] ?? 0)); $totalCostPrice = OrderItem::query() ->join('orders', 'order_items.order_id', '=', 'orders.id') ->leftJoin('product_prices', function ($join) { $join->on('order_items.product_variant_id', '=', 'product_prices.variant_id') ->where('product_prices.type', PriceType::HARGA_MODAL->value); }) ->where('orders.status', OrderStatus::COMPLETED) ->whereDate('orders.created_at', Carbon::today()) ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('orders.marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('orders.created_by_id', $user->id)) ->selectRaw('COALESCE(SUM(order_items.quantity * product_prices.price), 0) as total_hpp') ->value('total_hpp'); return [ 'total_revenue' => (int) ($revenueSummary->total_revenue ?? 0), 'total_discount' => (int) ($revenueSummary->total_discount ?? 0), 'total_marketplace_fees' => $totalMarketplaceFees, 'total_cost_price' => (int) ($totalCostPrice ?? 0), 'total_deduction' => (int) ($revenueSummary->total_discount ?? 0) + $totalMarketplaceFees + (int) ($totalCostPrice ?? 0), 'total_orders' => (int) ($revenueSummary->total_orders ?? 0), 'avg_order' => (int) ($revenueSummary->avg_order ?? 0), ]; } public function getExpenseSummary(): array { $today = Carbon::today(); /** @var User|null $user */ $user = auth()->user(); $isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false; $purchase = Purchase::query() ->whereDate('created_at', $today) ->when(! $isSuper, fn ($q) => $q->where('created_by_id', $user->id)) ->selectRaw('COALESCE(SUM(total), 0) as total') ->first(); $expenses = Expense::query() ->whereDate('created_at', $today) ->when(! $isSuper, fn ($q) => $q->where('created_by_id', $user->id)) ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); $employeeAdvance = EmployeeAdvance::query() ->whereDate('created_at', $today) ->when(! $isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id)) ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); $purchaseTotal = (int) ($purchase->total ?? 0); if ($user?->hasRole(Role::ADMIN_TOKO->value)) { $purchaseTotal = 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 { /** @var User|null $user */ $user = auth()->user(); $isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $byChannel = Order::query() ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('created_by_id', $user->id)) ->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() ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('created_by_id', $user->id)) ->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() ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('created_by_id', $user->id)) ->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() ->when(! $isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(! $isSuper && ! $isMarketing, fn ($q) => $q->where('created_by_id', $user->id)) ->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(), ]; } }