You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

516 lines
24 KiB

<?php
namespace App\Http\Controllers\system;
use App\Exports\ArrayExportH;
use App\Http\Controllers\Controller;
use App\Models\ExportFiles;
use App\Models\StatisticView;
use App\Models\EquipmentView;
use App\Models\MultisysEquipment;
use App\Models\OverSpeedRedEquipment;
use App\Models\User;
use App\Models\ViolationLaw;
use App\Models\ViolationParkingEquipment;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Facades\Excel;
class StatisticsController extends Controller
{
public function index(Request $request, $type)
{
$station = [];
$precinct = [];
$location = [];
$station = EquipmentView::select('station')->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);
}
}