toDateString(); if ($user && $this->isMarketingUser($user)) { $employee = $user->employee; if (! $employee) { return [ 'total_employees' => 0, 'present' => 0, 'absent' => 0, 'on_leave' => 0, 'percentage' => 0, ]; } $present = Attendance::where('employee_id', $employee->id) ->where('attendance_date', $today) ->count(); $onLeave = LeaveRequest::approved() ->where('employee_id', $employee->id) ->where('start_date', '<=', $today) ->where('end_date', '>=', $today) ->count(); $isWorking = ! in_array(Carbon::now()->dayOfWeek, [Carbon::SATURDAY, Carbon::SUNDAY]); $absent = $isWorking && $present === 0 && $onLeave === 0 ? 1 : 0; return [ 'total_employees' => 1, 'present' => $present, 'absent' => $absent, 'on_leave' => $onLeave, 'percentage' => $present > 0 ? 100 : 0, ]; } $totalEmployees = Employee::whereHas( 'user', fn ($q) => $q ->where('is_active', true) ->whereHas( 'roles', fn ($r) => $r ->whereHas( 'permissions', fn ($p) => $p ->where('name', 'attendances.create') ) ) )->count(); $present = Attendance::where('attendance_date', $today) ->whereHas( 'employee.user', fn ($q) => $q ->where('is_active', true) ->whereHas( 'roles', fn ($r) => $r ->whereHas( 'permissions', fn ($p) => $p ->where('name', 'attendances.create') ) ) )->count(); $onLeave = LeaveRequest::approved() ->where('start_date', '<=', $today) ->where('end_date', '>=', $today) ->whereHas( 'employee.user', fn ($q) => $q ->where('is_active', true) ->whereHas( 'roles', fn ($r) => $r ->whereHas( 'permissions', fn ($p) => $p ->where('name', 'attendances.create') ) ) )->count(); $absent = max(0, $totalEmployees - $present - $onLeave); return [ 'total_employees' => $totalEmployees, 'present' => $present, 'absent' => $absent, 'on_leave' => $onLeave, 'percentage' => $totalEmployees > 0 ? round(($present / $totalEmployees) * 100) : 0, ]; } public function getRevenueSummary(?User $user = null): array { $today = Carbon::now()->toDateString(); $baseQuery = Order::where('status', OrderStatus::COMPLETED) ->whereDate('created_at', $today); if ($user && $this->isMarketingUser($user)) { $baseQuery->where('marketing_id', $user->id); } $stats = (clone $baseQuery) ->selectRaw('COUNT(*) as total_orders') ->selectRaw('COALESCE(SUM(total_amount), 0) as total_revenue') ->selectRaw('COALESCE(SUM(discount), 0) as total_discount') ->selectRaw('COALESCE(SUM(nego_price), 0) as total_deduction') ->selectRaw('COALESCE(SUM(cogs), 0) as total_cogs') ->first(); $payrollTotal = (int) Payroll::where('status', PayrollStatus::PAID) ->whereDate('paid_at', $today) ->sum('total_amount'); $expenseTotal = (int) Expense::whereDate('created_at', $today) ->sum('amount'); $totalRevenue = (int) $stats->total_revenue; $totalCogs = (int) $stats->total_cogs; $gross = $totalRevenue - $totalCogs; $net = $gross - $payrollTotal - $expenseTotal; return [ 'total_revenue' => $totalRevenue, 'total_discount' => (int) $stats->total_discount, 'total_cogs' => $totalCogs, 'total_deduction' => (int) $stats->total_deduction, 'gross' => $gross, 'net' => $net, 'payroll_total' => $payrollTotal, 'expense_total' => $expenseTotal, 'total_orders' => (int) $stats->total_orders, ]; } public function getExpenseSummary(?User $user = null): array { $today = Carbon::now()->toDateString(); if ($user && $this->isMarketingUser($user)) { $employee = $user->employee; $expenseTotal = Expense::whereDate('created_at', $today) ->where('created_by_id', $user->id) ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); $advanceQuery = EmployeeAdvance::whereDate('created_at', $today) ->disbursed(); if ($employee) { $advanceQuery->where('employee_id', $employee->id); } else { $advanceQuery->whereRaw('0 = 1'); } $advanceTotal = $advanceQuery ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); return [ 'total' => (int) $expenseTotal->total + (int) $advanceTotal->total, 'expense_total' => (int) $expenseTotal->total, 'advance_total' => (int) $advanceTotal->total, ]; } $expenseTotal = Expense::whereDate('created_at', $today) ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); $advanceTotal = EmployeeAdvance::whereDate('created_at', $today) ->disbursed() ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); return [ 'total' => (int) $expenseTotal->total + (int) $advanceTotal->total, 'expense_total' => (int) $expenseTotal->total, 'advance_total' => (int) $advanceTotal->total, ]; } public function getOrderStats(?User $user = null): array { $today = Carbon::now()->toDateString(); $baseQuery = Order::whereDate('created_at', $today); if ($user && $this->isMarketingUser($user)) { $baseQuery->where('marketing_id', $user->id); } $byChannel = collect(OrderChannel::values())->map(function ($channel) use ($baseQuery) { $count = (clone $baseQuery)->where('channel', $channel)->count(); $label = OrderChannel::from($channel)->label(); return [ 'channel' => $channel, 'label' => $label, 'count' => $count, 'total' => (int) (clone $baseQuery)->where('channel', $channel)->sum('total_amount'), ]; }); $byPaymentType = collect(PaymentType::values())->map(function ($paymentType) use ($baseQuery) { $count = (clone $baseQuery)->where('payment_type', $paymentType)->count(); $label = PaymentType::from($paymentType)->label(); return [ 'payment_type' => $paymentType, 'label' => $label, 'count' => $count, 'total' => (int) (clone $baseQuery)->where('payment_type', $paymentType)->sum('total_amount'), ]; }); $byMarketing = (clone $baseQuery) ->whereNotNull('marketing_id') ->select('marketing_id') ->selectRaw('COUNT(*) as count') ->selectRaw('COALESCE(SUM(total_amount), 0) as total') ->groupBy('marketing_id') ->with('marketing:id') ->get() ->map(fn ($item) => [ 'name' => $item->marketing?->userProfile->full_name ?? '-', 'count' => $item->count, 'total' => (int) $item->total, ]); $byStatus = collect(OrderStatus::values())->map(function ($status) use ($baseQuery) { $count = (clone $baseQuery)->where('status', $status)->count(); $label = OrderStatus::from($status)->label(); return [ 'status' => $status, 'label' => $label, 'count' => $count, ]; }); return [ 'by_channel' => $byChannel, 'by_payment_type' => $byPaymentType, 'by_marketing' => $byMarketing, 'by_status' => $byStatus, ]; } public function getTodayAttendance(User $user): ?array { $employee = $user->employee; if (! $employee) { return null; } $attendance = Attendance::where('employee_id', $employee->id) ->where('attendance_date', now()->toDateString()) ->first(); if (! $attendance) { return null; } return [ 'id' => $attendance->id, 'attendance_date' => $attendance->attendance_date, 'check_in_at' => $attendance->check_in_at, 'check_out_at' => $attendance->check_out_at, 'check_in_photo' => null, 'check_out_photo' => null, 'check_in_latitude' => $attendance->check_in_latitude, 'check_in_longitude' => $attendance->check_in_longitude, 'check_out_latitude' => $attendance->check_out_latitude, 'check_out_longitude' => $attendance->check_out_longitude, 'work_duration_minutes' => $attendance->work_duration_minutes, ]; } public function isOnLeave(User $user): bool { $employee = $user->employee; if (! $employee) { return false; } return LeaveRequest::approved() ->where('employee_id', $employee->id) ->where('start_date', '<=', now()->toDateString()) ->where('end_date', '>=', now()->toDateString()) ->exists(); } private function isMarketingUser(User $user): bool { return $user->hasAnyRole([ Role::MARKETING_OFFLINE->value, Role::MARKETING_ONLINE->value, ]); } private function applyMarketingFilter(Builder $query, User $user, string $column = 'marketing_id'): Builder { if ($this->isMarketingUser($user)) { $query->where($column, $user->id); } return $query; } }