distinct()->pluck('station')->toArray(); $precinct = EquipmentView::select('precinct')->distinct()->pluck('precinct')->toArray(); $location = EquipmentView::select('location')->distinct()->pluck('location')->toArray(); $station = array_filter($station, function ($value) { return $value != null; }); $precinct = array_filter($precinct, function ($value) { return $value != null; }); $location = array_filter($location, function ($value) { return $value != null; }); // dd($station, $precinct, $location); if ($type == '1') { $violationTypes = ViolationLaw::getTypeCodes(); return view('system.statistics_1') ->with('violationTypes', $violationTypes) ->with('station', $station) ->with('precinct', $precinct) ->with('location', $location); } elseif ($type == '2') { $titles = ['未驗證', '已驗證舉發', '已驗證不舉發', '未處理比例']; return view('system.statistics_2') ->with('titles', $titles) ->with('station', $station) ->with('precinct', $precinct) ->with('location', $location); } elseif ($type == '3') { $titles = ['時間區間1已舉發件數', '時間區間2已舉發件數', '增減']; return view('system.statistics_3') ->with('titles', $titles) ->with('station', $station) ->with('precinct', $precinct) ->with('location', $location); } elseif ($type == '4') { $titles = ['已驗證舉發', '已驗證不舉發', '總件數']; return view('system.statistics_4') ->with('titles', $titles); } else { // 404 return view('errors.404'); } } public function getStatistics(Request $request) { $draw = $request->get('draw'); // Fetch records // $violationTypes = ['闖紅燈', '超速', '違停']; if ($request->group_at == '分局') { [$data_arr, $totalRecords] = self::getViolationSummary($request, '分局'); } else if ($request->group_at == '使用單位') { [$data_arr, $totalRecords] = self::getViolationSummary($request, '使用單位'); } else if ($request->group_at == 'user') { [$data_arr, $totalRecords] = self::getViolationSummary($request, 'user'); } else { [$data_arr, $totalRecords] = self::getViolationSummary($request, 'location'); } $response = array( "draw" => intval($draw), "iTotalRecords" => $totalRecords ?? 0, "iTotalDisplayRecords" => $totalRecords ?? 0, "aaData" => $data_arr ?? [] ); return $response; } public static function getViolationSummary($request, $group_at) { // dd($request->all()); if (isset($request->searchByFromdate)) $searchByFromdate = $request->searchByFromdate; if (isset($request->searchByTodate)) $searchByTodate = $request->searchByTodate; if (isset($request->searchByFromdate2)) $searchByFromdate2 = $request->searchByFromdate2; if (isset($request->searchByTodate2)) $searchByTodate2 = $request->searchByTodate2; if (isset($request->export)) $export = true; else $export = false; #region DataTable 搜尋屬性 if (!isset($request->export)) { $draw = $request->get('draw'); $start = $request->get("start"); $rowperpage = $request->get("length"); // Rows display per page $columnIndex_arr = $request->get('order'); $columnName_arr = $request->get('columns'); $order_arr = $request->get('order'); $search_arr = $request->get('search'); $columnIndex = $columnIndex_arr[0]['column']; // Column index $columnName = $columnName_arr[$columnIndex]['data']; // Column name $columnSortOrder = $order_arr[0]['dir']; // asc or desc $searchValue = $search_arr['value']; // Search value } else { $draw = 0; } #endregion #region Query 舉發類別分析表 if ($request->reportType == '1') { if ($group_at == '分局') { $groups = EquipmentView::getTypePrecinct($request->s1 ?? []); $groupLocationExpression = ''; $allSerialNumbers = []; foreach ($groups as $group => $serialnumbers) { $allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); $serialnumber = implode("','", $serialnumbers); if ($group == null || $group == '') continue; $groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; } $groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } else if ($group_at == '使用單位') { $groups = EquipmentView::getTypeStation($request->s2 ?? []); // dd($groups); $groupLocationExpression = ''; $allSerialNumbers = []; foreach ($groups as $group => $serialnumbers) { $allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); $serialnumber = implode("','", $serialnumbers); if ($group == null || $group == '') continue; $groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; } $groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } else { if (isset($request->s3) && $request->s3 != []) $allSerialNumbers = EquipmentView::whereIn('location', $request->s3 ?? [])->pluck('serialnumber')->toArray(); else $allSerialNumbers = EquipmentView::pluck('serialnumber')->toArray(); $groupLocationExpression = 'location AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } if (isset($searchByFromdate) && $searchByFromdate != '') { $starttime = Carbon::parse($searchByFromdate)->format('Y-m-d'); $q1 = "AND datatime >= '$starttime 00:00:00'"; } else { $q1 = ''; } if (isset($searchByTodate) && $searchByTodate != '') { $endtime = Carbon::parse($searchByTodate)->format('Y-m-d'); $q2 = "AND datatime <= '$endtime 23:59:59'"; } else { $q2 = ''; } $typeCodes = ViolationLaw::getTypeCodes(); foreach ($typeCodes as $type => $codes) { // where in violationcode in (codes) and violationtype = type and processcheck = 1 // 替每個code 加上引號 並用逗號隔開 包含頭尾 $codes = implode("','", $codes); $query->selectRaw("SUM(CASE WHEN violationcode IN ('$codes') AND processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '$type'"); } $query->selectRaw("SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS total_cases"); } // 審核統計分析表 else if ($request->reportType == '2') { if ($group_at == '分局') { $groups = EquipmentView::getTypePrecinct($request->s1 ?? []); $groupLocationExpression = ''; $allSerialNumbers = []; foreach ($groups as $group => $serialnumbers) { $allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); $serialnumber = implode("','", $serialnumbers); if ($group == null || $group == '') continue; $groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; } $groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } else if ($group_at == '使用單位') { $groups = EquipmentView::getTypeStation($request->s2 ?? []); $groupLocationExpression = ''; $allSerialNumbers = []; foreach ($groups as $group => $serialnumbers) { $allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); $serialnumber = implode("','", $serialnumbers); if ($group == null || $group == '') continue; $groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; } $groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } else { if (isset($request->s3) && $request->s3 != []) $allSerialNumbers = EquipmentView::whereIn('location', $request->s3 ?? [])->pluck('serialnumber')->toArray(); else $allSerialNumbers = EquipmentView::pluck('serialnumber')->toArray(); $groupLocationExpression = 'location AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } if (isset($searchByFromdate) && $searchByFromdate != '') { $starttime = Carbon::parse($searchByFromdate)->format('Y-m-d'); $q1 = "AND datatime >= '$starttime 00:00:00'"; } else { $q1 = ''; } if (isset($searchByTodate) && $searchByTodate != '') { $endtime = Carbon::parse($searchByTodate)->format('Y-m-d'); $q2 = "AND datatime <= '$endtime 23:59:59'"; } else { $q2 = ''; } $query->selectRaw("SUM(CASE WHEN processcheck = 0 $q1 $q2 THEN 1 ELSE 0 END) AS '未驗證'"); $query->selectRaw("SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '已驗證舉發'"); $query->selectRaw("SUM(CASE WHEN processcheck = 2 $q1 $q2 THEN 1 ELSE 0 END) AS '已驗證不舉發'"); // 未舉發比例 % = 未舉發 / (已舉發1 + 不舉發2 + 未舉發0) 直接顯示為 (比例數字) + %符號 保留兩位小數 $query->selectRaw("CONCAT(ROUND(SUM(CASE WHEN processcheck = 0 $q1 $q2 THEN 1 ELSE 0 END) / (SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) + SUM(CASE WHEN processcheck = 2 $q1 $q2 THEN 1 ELSE 0 END) + SUM(CASE WHEN processcheck = 0 $q1 $q2 THEN 1 ELSE 0 END) ) * 100, 2), '%') AS '未處理比例'"); $query->selectRaw("SUM(CASE WHEN processcheck IN ('0', '1', '2') $q1 $q2 THEN 1 ELSE 0 END) AS total_cases"); } else if ($request->reportType == '3') { if ($group_at == '分局') { $groups = EquipmentView::getTypePrecinct($request->s1 ?? []); $groupLocationExpression = ''; $allSerialNumbers = []; foreach ($groups as $group => $serialnumbers) { $allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); $serialnumber = implode("','", $serialnumbers); if ($group == null || $group == '') continue; $groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; } $groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } else if ($group_at == '使用單位') { $groups = EquipmentView::getTypeStation($request->s2 ?? []); $groupLocationExpression = ''; $allSerialNumbers = []; foreach ($groups as $group => $serialnumbers) { $allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); $serialnumber = implode("','", $serialnumbers); if ($group == null || $group == '') continue; $groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; } $groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } else { if (isset($request->s3) && $request->s3 != []) $allSerialNumbers = EquipmentView::whereIn('location', $request->s3 ?? [])->pluck('serialnumber')->toArray(); else $allSerialNumbers = EquipmentView::pluck('serialnumber')->toArray(); $groupLocationExpression = 'location AS group_location'; $query = StatisticView::selectRaw($groupLocationExpression); $query->whereIn('serialnumber', $allSerialNumbers); } if (isset($searchByFromdate) && $searchByFromdate != '' && isset($searchByTodate) && $searchByTodate != '') { $starttime = Carbon::parse($searchByFromdate)->format('Y-m-d'); $endtime = Carbon::parse($searchByTodate)->format('Y-m-d'); $q1 = "AND datatime >= '$starttime 00:00:00'"; $q2 = "AND datatime <= '$endtime 23:59:59'"; } else { $q1 = ''; $q2 = ''; } if (isset($searchByFromdate2) && $searchByFromdate2 != '' && isset($searchByTodate2) && $searchByTodate2 != '') { $starttime2 = Carbon::parse($searchByFromdate2)->format('Y-m-d'); $endtime2 = Carbon::parse($searchByTodate2)->format('Y-m-d'); $q3 = "AND datatime >= '$starttime2 00:00:00'"; $q4 = "AND datatime <= '$endtime2 23:59:59'"; } else { $q3 = ''; $q4 = ''; } $query->selectRaw("SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '時間區間1已舉發件數'"); $query->selectRaw("SUM(CASE WHEN processcheck = 1 $q3 $q4 THEN 1 ELSE 0 END) AS '時間區間2已舉發件數'"); // 時間區間2 - 時間區間1 $query->selectRaw("SUM(CASE WHEN processcheck = 1 $q3 $q4 THEN 1 ELSE 0 END) - SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '增減'"); } // 審核統計分析表 else if ($request->reportType == '4') { // distinct user account $users = User::select('account')->distinct()->pluck('account')->toArray(); $users = array_filter($users, function ($value) { return $value != null; }); // StatisticView 的jsoncheck是 user account 依據 user account 分組統計 processcheck = 1 的數量 跟 processcheck = 2 的數量 還有總數 $query = StatisticView::selectRaw("jsoncheck"); // 增加一條join 用來取得 user account 關聯的 name $query->leftJoin('users', 'users.account', '=', 'jsoncheck'); $query->selectRaw("users.name AS 'group_location'"); $query->selectRaw("SUM(CASE WHEN processcheck = 1 THEN 1 ELSE 0 END) AS '已驗證舉發'"); $query->selectRaw("SUM(CASE WHEN processcheck = 2 THEN 1 ELSE 0 END) AS '已驗證不舉發'"); $query->selectRaw("SUM(CASE WHEN processcheck IN ('1', '2') THEN 1 ELSE 0 END) AS 總件數"); // jsoncheck AS group_location is not null $query->whereNotNull('jsoncheck'); $query->where('jsoncheck', '!=', 'admin'); $query->groupBy('group_location'); } #endregion // 所有 processcheck = 1 的案件 $query->groupBy('group_location'); if (isset($columnName)) $query->orderBy($columnName, $columnSortOrder); $data = $query->get(); $count = count($data); if (!$export) { if (isset($start)) $query->skip($start); if (isset($rowperpage)) $query->take($rowperpage); } $data = $query->get(); // 如果data[i] 底下的 group_location 是 null 就不顯示' $data = $data->filter(function ($value, $key) { return $value->group_location != null; }); return [$data, $count]; } public function getStatisticsExport(Request $request) { #region Request 搜尋值 if (isset($request->searchByFromdate)) $searchByFromdate = $request->searchByFromdate; else $searchByFromdate = ''; if (isset($request->searchByTodate)) $searchByTodate = $request->searchByTodate; else $searchByTodate = ''; #endregion #region DataTable 搜尋屬性 if (!isset($request->export)) { $draw = $request->get('draw'); $start = $request->get("start"); $rowperpage = $request->get("length"); // Rows display per page $columnIndex_arr = $request->get('order'); $columnName_arr = $request->get('columns'); $order_arr = $request->get('order'); $search_arr = $request->get('search'); $columnIndex = $columnIndex_arr[0]['column']; // Column index $columnName = $columnName_arr[$columnIndex]['data']; // Column name $columnSortOrder = $order_arr[0]['dir']; // asc or desc $searchValue = $search_arr['value']; // Search value } else { $draw = 0; } if ($request->group_at == '分局') { $title = '分局'; [$data_arr, $totalRecords] = self::getViolationSummary($request, '分局'); } else if ($request->group_at == '使用單位') { $title = '使用單位'; [$data_arr, $totalRecords] = self::getViolationSummary($request, '使用單位'); } else if ($request->group_at == 'user') { $title = '員警姓名'; [$data_arr, $totalRecords] = self::getViolationSummary($request, 'user'); } else { $title = '路口'; [$data_arr, $totalRecords] = self::getViolationSummary($request, 'location'); } if ($request->reportType == '1') { $titlef = '舉發類別分析表'; } else if ($request->reportType == '2') { $titlef = '審核統計分析表'; } else if ($request->reportType == '3') { $titlef = '審核統計分析表'; } else if ($request->reportType == '4') { $titlef = '個別案件審核統計表'; } $remark = '報表-' . $titlef . '-' . $title; $columns = ['group_location', 'total_cases']; if ($request->reportType == '1') { $typeCodes = ViolationLaw::getTypeCodes(); foreach ($typeCodes as $type => $codes) { if ($type == 99 || $type == 3 || $type == 1) { continue; } $columns[] = $type; } } else if ($request->reportType == '2') { $columns = ['group_location', 'total_cases', '未驗證', '已驗證舉發', '已驗證不舉發', '未處理比例']; } else if ($request->reportType == '3') { $columns = ['group_location', '時間區間1已舉發件數', '時間區間2已舉發件數', '增減']; } else if ($request->reportType == '4') { $columns = ['group_location', '已驗證舉發', '已驗證不舉發', '總件數']; } if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { $remark = $remark . ' ' . $request->searchByFromdate . ' ~ ' . $request->searchByTodate; } $data_arr = $data_arr->toArray(); $data = array_map(function ($row) use ($columns) { $data = array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); return $data; }, $data_arr); if ($request->reportType == '1' || $request->reportType == '2') { $column2 = [$title, '總案件數']; } else { $column2 = [$title]; } foreach ($columns as $column) { if ($column == 'group_location' || $column == 'total_cases') { continue; } $column2[] = $column; } if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { $timeRange = $request->searchByFromdate . ' ~ ' . $request->searchByTodate; } else { $timeRange = ''; } $columnTitle = [ ["【表單名稱】: " . $remark], ["【查詢日期區間】: " . $timeRange], $column2 ]; $fileName = 'statistics-' . Str::random(10) . '.xlsx'; try { DB::beginTransaction(); ExportFiles::create([ 'name' => $fileName, 'path' => 'public/exports', 'type' => 'xlsx', 'status' => '1', 'remark' => "$remark", 'user_id' => auth('api')->user()->id, ]); $option = [ 'printDef' => $request->printDef ?? 0, 'showPN' => $request->showPN ?? 0, 'showBorder' => $request->showBorder ?? 0, ]; Excel::store(new ArrayExportH($data, $columnTitle, $option), 'public/exports/' . $fileName, 'local', \Maatwebsite\Excel\Excel::XLSX); DB::commit(); } catch (\Throwable $th) { Log::error("報表匯出失敗: " . $th->getMessage()); DB::rollBack(); } return response()->json(['url' => route('export', ['fileName' => $fileName])], 200); } }