diff --git a/app/Http/Controllers/Admin/AnalysisController.php b/app/Http/Controllers/Admin/AnalysisController.php index 2782f51..f576168 100644 --- a/app/Http/Controllers/Admin/AnalysisController.php +++ b/app/Http/Controllers/Admin/AnalysisController.php @@ -3,19 +3,40 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Services\System\DashboardService; +use Carbon\Carbon; use Illuminate\Http\Request; use Inertia\Inertia; use Inertia\Response; class AnalysisController extends Controller { + public function __construct( + private readonly DashboardService $dashboardService, + ) {} + public function index(Request $request): Response { + $startDate = $request->query('start_date') ? Carbon::parse($request->query('start_date'))->startOfDay() : null; + $endDate = $request->query('end_date') ? Carbon::parse($request->query('end_date'))->endOfDay() : null; + return Inertia::render('admin/Analysis', [ 'filters' => [ - 'search' => $request->query('search', ''), - 'status' => $request->query('status', ''), + 'start_date' => $request->query('start_date', ''), + 'end_date' => $request->query('end_date', ''), ], + 'rawMaterialStock' => $this->dashboardService->getRawMaterialStock(), + 'productStock' => $this->dashboardService->getProductStock(), + 'kasbonSummary' => $this->dashboardService->getKasbonSummary($startDate, $endDate), + 'leaveRequestSummary' => $this->dashboardService->getLeaveRequestSummary($startDate, $endDate), + 'lowStockProducts' => $this->dashboardService->getLowStockProducts(), + 'lowStockMaterials' => $this->dashboardService->getLowStockMaterials(), + 'attendanceToday' => $this->dashboardService->getAttendanceToday($startDate, $endDate), + 'cashAccounts' => $this->dashboardService->getCashAccounts(), + 'cashSummary' => $this->dashboardService->getCashSummary($startDate, $endDate), + 'purchaseSummary' => $this->dashboardService->getPurchaseSummary($startDate, $endDate), + 'monthlyExpenses' => $this->dashboardService->getMonthlyExpenses($startDate, $endDate), + 'revenueSummary' => $this->dashboardService->getRevenueSummary($startDate, $endDate), ]); } } diff --git a/app/Http/Controllers/Admin/DashboardController.php b/app/Http/Controllers/Admin/DashboardController.php index 2037598..983bf79 100644 --- a/app/Http/Controllers/Admin/DashboardController.php +++ b/app/Http/Controllers/Admin/DashboardController.php @@ -20,29 +20,27 @@ public function index(): Response $startOfMonth = $now->copy()->startOfMonth(); $endOfMonth = $now->copy()->endOfMonth(); + $startOfDay = Carbon::today()->startOfDay(); + $endOfDay = Carbon::today()->endOfDay(); + return Inertia::render('admin/Dashboard', [ - 'rawMaterialStock' => $this->dashboardService->getRawMaterialStock(), - 'productStock' => $this->dashboardService->getProductStock(), - 'lowStockProducts' => $this->dashboardService->getLowStockProducts(), - 'lowStockMaterials' => $this->dashboardService->getLowStockMaterials(), 'topSuppliers' => $this->dashboardService->getTopSuppliers(), 'topCustomers' => $this->dashboardService->getTopCustomers(), 'topProducts' => $this->dashboardService->getTopProducts(), - 'purchaseSummary' => $this->dashboardService->getPurchaseSummary(), + 'purchaseSummary' => $this->dashboardService->getPurchaseSummary($startOfDay, $endOfDay), 'cuttingSummary' => $this->dashboardService->getCuttingSummary(), 'cuttingByStatus' => $this->dashboardService->getCuttingByStatus(), 'orderStats' => $this->dashboardService->getOrderStats(), - 'revenueSummary' => $this->dashboardService->getRevenueSummary(), + 'revenueSummary' => $this->dashboardService->getRevenueSummary($startOfDay, $endOfDay), 'marketplaceSummary' => $this->dashboardService->getMarketplaceSummary(), 'cashAccounts' => $this->dashboardService->getCashAccounts(), - 'cashSummary' => $this->dashboardService->getCashSummary($startOfMonth, $endOfMonth), + 'cashSummary' => $this->dashboardService->getCashSummary($startOfDay, $endOfDay), 'monthlyCashFlow' => $this->dashboardService->getMonthlyCashFlow(), - 'monthlyExpenses' => $this->dashboardService->getMonthlyExpenses($startOfMonth, $endOfMonth), - 'kasbonSummary' => $this->dashboardService->getKasbonSummary(), + 'monthlyExpenses' => $this->dashboardService->getMonthlyExpenses($startOfDay, $endOfDay), + 'kasbonSummary' => $this->dashboardService->getKasbonSummary($startOfDay, $endOfDay), 'payrollSummary' => $this->dashboardService->getPayrollSummary($startOfMonth, $endOfMonth), - 'leaveRequestSummary' => $this->dashboardService->getLeaveRequestSummary($startOfMonth, $endOfMonth), 'employeeSummary' => $this->dashboardService->getEmployeeSummary(), - 'attendanceToday' => $this->dashboardService->getAttendanceToday(), + 'attendanceToday' => $this->dashboardService->getAttendanceToday($startOfDay, $endOfDay), 'monthlyRevenueTrend' => $this->dashboardService->getMonthlyRevenueTrend(), 'monthlyPurchaseTrend' => $this->dashboardService->getMonthlyPurchaseTrend(), ]); diff --git a/app/Services/System/DashboardService.php b/app/Services/System/DashboardService.php index 2532f47..1907ed8 100644 --- a/app/Services/System/DashboardService.php +++ b/app/Services/System/DashboardService.php @@ -167,10 +167,13 @@ public function getTopProducts(): array ->toArray(); } - public function getPurchaseSummary(): array + public function getPurchaseSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $purchaseSummary = Purchase::query() - ->selectRaw('COUNT(*) as total_purchases, SUM(total) as total_spent, SUM(discount) as total_discount') + $query = Purchase::query(); + if ($startDate && $endDate) { + $query->whereBetween('created_at', [$startDate, $endDate]); + } + $purchaseSummary = $query->selectRaw('COUNT(*) as total_purchases, SUM(total) as total_spent, SUM(discount) as total_discount') ->first(); return [ @@ -269,17 +272,20 @@ public function getOrderStats(): array ]; } - public function getRevenueSummary(): array + public function getRevenueSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $revenueSummary = Order::query() - ->completed() - ->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') + $query = Order::query()->completed(); + if ($startDate && $endDate) { + $query->whereBetween('created_at', [$startDate, $endDate]); + } + $revenueSummary = $query->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') - ->get() + $feesQuery = Order::query()->completed()->whereNotNull('marketplace_settings_snapshot'); + if ($startDate && $endDate) { + $feesQuery->whereBetween('created_at', [$startDate, $endDate]); + } + $totalMarketplaceFees = $feesQuery->get() ->sum(fn ($order) => (int) ($order->marketplace_settings_snapshot['total_fee_amount'] ?? 0)); return [ @@ -326,11 +332,13 @@ public function getCashAccounts(): array ->toArray(); } - public function getCashSummary(Carbon $startOfMonth, Carbon $endOfMonth): array + public function getCashSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $summary = CashTransaction::query() - ->whereBetween('created_at', [$startOfMonth, $endOfMonth]) - ->selectRaw(" + $query = CashTransaction::query(); + if ($startDate && $endDate) { + $query->whereBetween('created_at', [$startDate, $endDate]); + } + $summary = $query->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 @@ -378,11 +386,13 @@ public function getMonthlyCashFlow(): array return $result->toArray(); } - public function getMonthlyExpenses(Carbon $startOfMonth, Carbon $endOfMonth): array + public function getMonthlyExpenses(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $monthlyExpenses = Expense::query() - ->whereBetween('created_at', [$startOfMonth, $endOfMonth]) - ->selectRaw('COALESCE(SUM(amount), 0) as total, COUNT(*) as count') + $query = Expense::query(); + if ($startDate && $endDate) { + $query->whereBetween('created_at', [$startDate, $endDate]); + } + $monthlyExpenses = $query->selectRaw('COALESCE(SUM(amount), 0) as total, COUNT(*) as count') ->first(); return [ @@ -391,26 +401,24 @@ public function getMonthlyExpenses(Carbon $startOfMonth, Carbon $endOfMonth): ar ]; } - public function getKasbonSummary(): array + public function getKasbonSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $pending = EmployeeAdvance::query() - ->pending() - ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total') - ->first(); + $pendingQuery = EmployeeAdvance::query()->pending(); + $approvedQuery = EmployeeAdvance::query()->approved(); + $paidQuery = EmployeeAdvance::query()->paid(); + $employeeQuery = EmployeeAdvance::query(); - $approved = EmployeeAdvance::query() - ->approved() - ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total') - ->first(); + if ($startDate && $endDate) { + $pendingQuery->whereBetween('created_at', [$startDate, $endDate]); + $approvedQuery->whereBetween('created_at', [$startDate, $endDate]); + $paidQuery->whereBetween('created_at', [$startDate, $endDate]); + $employeeQuery->whereBetween('created_at', [$startDate, $endDate]); + } - $paid = EmployeeAdvance::query() - ->paid() - ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total') - ->first(); - - $totalEmployees = EmployeeAdvance::query() - ->distinct('employee_id') - ->count('employee_id'); + $pending = $pendingQuery->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total')->first(); + $approved = $approvedQuery->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total')->first(); + $paid = $paidQuery->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total')->first(); + $totalEmployees = $employeeQuery->distinct('employee_id')->count('employee_id'); return [ 'pending' => [ @@ -473,14 +481,16 @@ public function getPayrollSummary(Carbon $startOfMonth, Carbon $endOfMonth): arr ]; } - public function getLeaveRequestSummary(Carbon $startOfMonth, Carbon $endOfMonth): array + public function getLeaveRequestSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $leaveRequestSummary = LeaveRequest::query() - ->where(function ($query) use ($startOfMonth, $endOfMonth) { - $query->whereBetween('start_date', [$startOfMonth, $endOfMonth]) - ->orWhereBetween('end_date', [$startOfMonth, $endOfMonth]); - }) - ->selectRaw(" + $query = LeaveRequest::query(); + if ($startDate && $endDate) { + $query->where(function ($query) use ($startDate, $endDate) { + $query->whereBetween('start_date', [$startDate, $endDate]) + ->orWhereBetween('end_date', [$startDate, $endDate]); + }); + } + $leaveRequestSummary = $query->selectRaw(" COUNT(*) as total, SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending_count, SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END) as approved_count, @@ -516,35 +526,58 @@ public function getEmployeeSummary(): array ]; } - public function getAttendanceToday(): array + public function getAttendanceToday(?Carbon $startDate = null, ?Carbon $endDate = null): array { - $today = Carbon::today(); - $totalEmployees = Employee::query()->count(); - $present = Attendance::query() - ->where('attendance_date', $today) - ->distinct('employee_id') - ->count('employee_id'); + if ($startDate && $endDate) { + $present = Attendance::query() + ->whereBetween('attendance_date', [$startDate, $endDate]) + ->count(); - // Karyawan yang sedang cuti hari ini (approved & aktif hari ini) - $onLeave = LeaveRequest::query() - ->approved() - ->where('start_date', '<=', $today) - ->where('end_date', '>=', $today) - ->distinct('employee_id') - ->count('employee_id'); + $onLeave = LeaveRequest::query() + ->approved() + ->where(function ($query) use ($startDate, $endDate) { + $query->whereBetween('start_date', [$startDate, $endDate]) + ->orWhereBetween('end_date', [$startDate, $endDate]); + }) + ->count(); - // Absent = tidak hadir & tidak sedang cuti - $notPresent = max(0, $totalEmployees - $present); - $absent = max(0, $notPresent - $onLeave); + $days = (int) $startDate->copy()->startOfDay()->diffInDays($endDate->copy()->startOfDay()) + 1; + $totalPossible = $totalEmployees * $days; + $absent = max(0, $totalPossible - $present - $onLeave); - return [ - 'total_employees' => $totalEmployees, - 'present' => $present, - 'absent' => $absent, - 'on_leave' => $onLeave, - ]; + return [ + 'total_employees' => (int) $totalPossible, + 'present' => (int) $present, + 'absent' => (int) $absent, + 'on_leave' => (int) $onLeave, + ]; + } else { + $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'); + + $notPresent = max(0, $totalEmployees - $present); + $absent = max(0, $notPresent - $onLeave); + + return [ + 'total_employees' => $totalEmployees, + 'present' => $present, + 'absent' => $absent, + 'on_leave' => $onLeave, + ]; + } } public function getMonthlyRevenueTrend(): array diff --git a/resources/js/pages/admin/Analysis.vue b/resources/js/pages/admin/Analysis.vue index 2bf2756..f3bbb87 100644 --- a/resources/js/pages/admin/Analysis.vue +++ b/resources/js/pages/admin/Analysis.vue @@ -1,4 +1,8 @@