filter; if (!$selectedPlant || !$selectedInvoice) { return [ 'datasets' => [], 'labels' => [], ]; } if ($activeFilter === 'yesterday') { $startDate = now()->subDay()->setTime(8, 0, 0); $endDate = now()->setTime(8, 0, 0); $groupBy = 'hour'; } elseif ($activeFilter === 'this_week') { $startDate = now()->startOfWeek()->setTime(8, 0, 0); $endDate = now()->endOfWeek()->addDay()->setTime(8, 0, 0); $groupBy = 'day_of_week'; } elseif ($activeFilter === 'this_month') { $startDate = now()->startOfMonth(); $endDate = now()->endOfMonth(); $groupBy = 'week_of_month'; } else { $startDate = now()->setTime(8, 0, 0); $endDate = now()->copy()->addDay()->setTime(8, 0, 0); $groupBy = 'hour'; } // Get fully scanned invoices if ($selectedInvoice === 'individual_material') { $allInvoiceNumbers = \DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->where('quantity', 1) ->groupBy('invoice_number') ->pluck('invoice_number'); $fullyScannedInvoiceNumbers = \DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->where('quantity', 1) ->groupBy('invoice_number') ->havingRaw("SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END) = COUNT(*)") ->pluck('invoice_number'); } //elseif ($selectedInvoice === 'bundle_material') { // $allInvoiceNumbers = \DB::table('invoice_validations') // ->select('invoice_number') // ->where('plant_id', $selectedPlant) // ->havingRaw('MIN(quantity) > 1') // ->groupBy('invoice_number') // ->pluck('invoice_number'); // $fullyScannedInvoiceNumbers = \DB::table('invoice_validations') // ->select('invoice_number') // ->where('plant_id', $selectedPlant) // ->havingRaw('MIN(quantity) > 1') // ->groupBy('invoice_number') // ->havingRaw("SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END) = COUNT(*)") // ->pluck('invoice_number'); // } else if($selectedInvoice === 'serial_invoice') { $allInvoiceNumbers = \DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->whereNull('quantity') ->pluck('invoice_number'); $fullyScannedInvoiceNumbers = \DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->whereNull('quantity') ->groupBy('invoice_number') ->havingRaw("SUM(CASE WHEN scanned_status = 'Scanned' THEN 1 ELSE 0 END) = COUNT(*)") ->pluck('invoice_number'); } if ($selectedInvoice === 'bundle_material') { //Get all invoice numbers that contain bundle materials $allInvoiceNumbers = DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->whereIn('invoice_number', function ($query) use ($selectedPlant) { $query->select('invoice_number') ->from('invoice_validations') ->where('plant_id', $selectedPlant) ->where('quantity', '>', 1); }) ->groupBy('invoice_number') ->pluck('invoice_number'); //Get fully scanned bundle invoices $fullyScannedBundle = DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->where('quantity', '>', 1) ->groupBy('invoice_number') ->havingRaw("SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END) = COUNT(*)") ->pluck('invoice_number'); //Get individual invoice numbers $individualInvoices = DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->where('quantity', 1) ->groupBy('invoice_number') ->pluck('invoice_number'); //Get fully scanned individual invoices $fullyScannedIndividual = DB::table('invoice_validations') ->select('invoice_number') ->where('plant_id', $selectedPlant) ->where('quantity', 1) ->groupBy('invoice_number') ->havingRaw("SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END) = COUNT(*)") ->pluck('invoice_number'); //Find common invoices between bundle and individual $commonInvoices = $allInvoiceNumbers->intersect($individualInvoices); //Identify incomplete common invoices $notScannedInvoicesForBundle = $commonInvoices->filter(function ($invoice) use ($fullyScannedIndividual, $fullyScannedBundle) { return !($fullyScannedIndividual->contains($invoice) && $fullyScannedBundle->contains($invoice)); }); //Final fully scanned = only those that are scanned in both individual & bundle $fullyScannedInvoiceNumbers = $fullyScannedBundle->filter(function ($invoice) use ($fullyScannedIndividual) { return $fullyScannedIndividual->contains($invoice); }); //Exclude invoices that should be marked as "not scanned" $fullyScannedInvoiceNumbers = $fullyScannedInvoiceNumbers->diff($notScannedInvoicesForBundle); //Calculate not scanned invoices = all - fully scanned $notScannedInvoiceNumbers = $allInvoiceNumbers->diff($fullyScannedInvoiceNumbers); } // Not scanned = all - scanned $notScannedInvoiceNumbers = $allInvoiceNumbers->diff($fullyScannedInvoiceNumbers); //Get timestamps $scannedTimestamps = \DB::table('invoice_validations') ->selectRaw("MAX(updated_at) AS final_time, invoice_number") ->where('plant_id', $selectedPlant) ->whereIn('invoice_number', $fullyScannedInvoiceNumbers) ->whereBetween('updated_at', [$startDate, $endDate]) ->groupBy('invoice_number') ->pluck('final_time', 'invoice_number'); $notScannedTimestamps = \DB::table('invoice_validations') ->selectRaw("MIN(created_at) AS first_time, invoice_number") ->where('plant_id', $selectedPlant) ->whereIn('invoice_number', $notScannedInvoiceNumbers) ->whereBetween('created_at', [$startDate, $endDate]) ->groupBy('invoice_number') ->pluck('first_time', 'invoice_number'); // Group timestamps $scannedGrouped = []; $notScannedGrouped = []; foreach ($scannedTimestamps as $timestamp) { $time = \Carbon\Carbon::parse($timestamp); if ($time->lt($startDate) || $time->gt($endDate)) continue; $key = match ($groupBy) { 'hour' => (int) $time->format('G'), 'day_of_week' => (int) $time->dayOfWeek, 'week_of_month' => (int) ceil($time->day / 7), }; $scannedGrouped[$key] = ($scannedGrouped[$key] ?? 0) + 1; } foreach ($notScannedTimestamps as $timestamp) { $time = \Carbon\Carbon::parse($timestamp); if ($time->lt($startDate) || $time->gt($endDate)) continue; $key = match ($groupBy) { 'hour' => (int) $time->format('G'), 'day_of_week' => (int) $time->dayOfWeek, 'week_of_month' => (int) ceil($time->day / 7), }; $notScannedGrouped[$key] = ($notScannedGrouped[$key] ?? 0) + 1; } // Build x-axis labels and data arrays if ($groupBy === 'hour') { $shiftedKeys = array_merge(range(8, 23), range(0, 7)); $labels = array_map(fn($h) => date("g A", strtotime("$h:00")), $shiftedKeys); $scannedData = array_map(fn($h) => $scannedGrouped[$h] ?? 0, $shiftedKeys); $notScannedData = array_map(fn($h) => $notScannedGrouped[$h] ?? 0, $shiftedKeys); } elseif ($groupBy === 'day_of_week') { $labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; $scannedData = array_fill(0, 7, 0); $notScannedData = array_fill(0, 7, 0); foreach ($scannedGrouped as $k => $v) $scannedData[$k] = $v; foreach ($notScannedGrouped as $k => $v) $notScannedData[$k] = $v; // Shift so Monday starts first $scannedData = [$scannedData[1], $scannedData[2], $scannedData[3], $scannedData[4], $scannedData[5], $scannedData[6], $scannedData[0]]; $notScannedData = [$notScannedData[1], $notScannedData[2], $notScannedData[3], $notScannedData[4], $notScannedData[5], $notScannedData[6], $notScannedData[0]]; } else { $weeksCount = ceil($endDate->day / 7); $labels = []; for ($i = 1; $i <= $weeksCount; $i++) { $weekStart = $startDate->copy()->addDays(($i - 1) * 7)->format('d M'); $weekEnd = $startDate->copy()->addDays($i * 7 - 1)->min($endDate)->format('d M'); $labels[] = "Week $i ($weekStart - $weekEnd)"; } $scannedData = array_fill(1, $weeksCount, 0); $notScannedData = array_fill(1, $weeksCount, 0); foreach ($scannedGrouped as $k => $v) $scannedData[$k] = $v; foreach ($notScannedGrouped as $k => $v) $notScannedData[$k] = $v; $scannedData = array_values($scannedData); $notScannedData = array_values($notScannedData); } return [ 'datasets' => [ [ 'label' => 'Scanned Invoices', 'data' => $scannedData, 'borderColor' => 'rgba(75, 192, 192, 1)', 'backgroundColor' => 'rgba(23, 211, 80, 0.7)', 'fill' => false, 'tension' => 0.3, ], [ 'label' => 'Not Scanned Invoices', 'data' => $notScannedData, 'borderColor' => 'rgba(255, 99, 132, 1)', 'backgroundColor' => 'rgba(214, 105, 32, 0.9)', 'fill' => false, 'tension' => 0.3, ], ], 'labels' => $labels, ]; } protected function getType(): string { return 'bar'; } public static function getDefaultName(): string { return 'invoice-chart'; } protected function getOptions(): array { return [ 'scales' => [ 'y' => [ 'beginAtZero' => true, //Start Y-axis from 0 'ticks' => [ 'stepSize' => 1, ], ], ], ]; } protected function getFilters(): ?array { return [ 'today' => 'Today', 'yesterday' => 'Yesterday', 'this_week'=> 'This Week', 'this_month'=> 'This Month', ]; } public static function canView(): bool { // dd('Checking route:', request()->route()->getName()); // to avoid showing the widget in other pages return request()->routeIs('filament.admin.pages.invoice-dashboard'); } }