From 8d138b83390d6a066862b2fcd8213f860ed7750d Mon Sep 17 00:00:00 2001 From: amirghasempoor Date: Tue, 15 Apr 2025 10:45:47 +0330 Subject: [PATCH] add group by feature to datatable --- app/Facades/DataTable/DataTable.php | 9 +- .../Dashboard/SafetyAndPrivacyController.php | 7 + app/Models/RahdariPointHistory.php | 5 + .../SafetyAndPrivacyTableService.php | 177 +++++------------- app/Services/DataTable/DataTableInput.php | 6 + app/Services/DataTable/DataTableService.php | 16 +- 6 files changed, 91 insertions(+), 129 deletions(-) diff --git a/app/Facades/DataTable/DataTable.php b/app/Facades/DataTable/DataTable.php index ae637a86..86d25fe6 100644 --- a/app/Facades/DataTable/DataTable.php +++ b/app/Facades/DataTable/DataTable.php @@ -28,7 +28,8 @@ class DataTable array $allowedFilters = [], array $allowedRelations = [], array $allowedSortings = [], - array $allowedSelects = [] + array $allowedSelects = [], + ?array $allowedGroupBy = null ): array { @@ -43,7 +44,8 @@ class DataTable $sorting, $rels, $allowedFilters, - $allowedSortings + $allowedSortings, + $allowedGroupBy ); $query = $this->makeQueryFromModel($mixed); @@ -52,7 +54,8 @@ class DataTable ->setAllowedFilters($allowedFilters) ->setAllowedRelations($allowedRelations) ->setAllowedSortings($allowedSortings) - ->setAllowedSelects($allowedSelects); + ->setAllowedSelects($allowedSelects) + ->setAllowedGroupBy($allowedGroupBy); return $dataTableService->getData(); } diff --git a/app/Http/Controllers/V3/Dashboard/SafetyAndPrivacyController.php b/app/Http/Controllers/V3/Dashboard/SafetyAndPrivacyController.php index 5741f4ff..693a1864 100644 --- a/app/Http/Controllers/V3/Dashboard/SafetyAndPrivacyController.php +++ b/app/Http/Controllers/V3/Dashboard/SafetyAndPrivacyController.php @@ -24,16 +24,23 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Validator; use Maatwebsite\Excel\Facades\Excel; use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Throwable; class SafetyAndPrivacyController extends Controller { use ApiResponse; + /** + * @throws Throwable + */ public function index(Request $request, SafetyAndPrivacyTableService $safetyAndPrivacyTableService): JsonResponse { return response()->json($safetyAndPrivacyTableService->datatable($request)); } + /** + * @throws Throwable + */ public function excelReport(Request $request, SafetyAndPrivacyTableService $safetyAndPrivacyTableService): BinaryFileResponse { $name = 'گزارش از نگهداری حریم راه ' . verta()->now()->format('Y-m-d H-i') . '.xlsx'; diff --git a/app/Models/RahdariPointHistory.php b/app/Models/RahdariPointHistory.php index e8d2e9fd..c6d359bc 100644 --- a/app/Models/RahdariPointHistory.php +++ b/app/Models/RahdariPointHistory.php @@ -13,6 +13,11 @@ class RahdariPointHistory extends Model */ protected $fillable = [ 'user_id', + 'previous_province_id', + 'previous_province_name', + 'previous_city_id', + 'previous_city_name', + 'previous_name', 'previous_status', 'previous_type', 'previous_team_num', diff --git a/app/Services/Cartables/SafetyAndPrivacyTableService.php b/app/Services/Cartables/SafetyAndPrivacyTableService.php index 891999cc..304c3532 100644 --- a/app/Services/Cartables/SafetyAndPrivacyTableService.php +++ b/app/Services/Cartables/SafetyAndPrivacyTableService.php @@ -2,17 +2,22 @@ namespace App\Services\Cartables; +use App\Exceptions\ProhibitedAction; use App\Facades\DataTable\DataTableFacade; use App\Http\Traits\ApiResponse; use App\Models\Province; use App\Models\SafetyAndPrivacy; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use Throwable; class SafetyAndPrivacyTableService { use ApiResponse; + /** + * @throws Throwable + */ public function dataTable(Request $request, $loadRelations = false) { $user = auth()->user(); @@ -27,16 +32,12 @@ class SafetyAndPrivacyTableService $query = SafetyAndPrivacy::query()->select($fields); } elseif ($user->hasPermissionTo('show-safety-and-privacy-operator-cartable-province')) { - if (is_null($user->province_id)) { - return $this->errorResponse('استانی برای شما در سامانه ثبت نشده است!'); - } + throw_if(is_null($user->province_id), new ProhibitedAction('استانی برای شما در سامانه ثبت نشده است!')); $query = SafetyAndPrivacy::query()->where('province_id', '=', $user->province_id)->select($fields); } elseif ($user->hasPermissionTo('show-safety-and-privacy-operator-cartable-edarate-shahri')) { - if (is_null($user->edarate_shahri_id)) { - return $this->errorResponse('اداره ای برای شما در سامانه ثبت نشده است!'); - } + throw_if(is_null($user->edarate_shahri_id), new ProhibitedAction('اداره ای برای شما در سامانه ثبت نشده است!')); $query = SafetyAndPrivacy::query()->where('edare_shahri_id', '=', $user->edarate_shahri_id); } @@ -51,74 +52,45 @@ class SafetyAndPrivacyTableService public function countryActivity(Request $request): array { - $fromDate = $request->from_date ? $request->from_date . ' 00:00:00' : now()->startOfDay()->toDateTimeString(); - $toDate = $request->date_to ? $request->date_to . ' 23:59:59' : now()->endOfDay()->toDateTimeString(); - $axisTypeId = $request->axis_type_id; - $activities = []; + $countryQuery = SafetyAndPrivacy::query()->selectRaw('COUNT(*) as qty,info_id, step'); - $country = SafetyAndPrivacy::query() - ->selectRaw('COUNT(*) as qty,info_id, step') - ->whereBetween('created_at', [$fromDate, $toDate]) - ->when($axisTypeId, function ($query) use ($axisTypeId) { - $query->where('axis_type_id', '=', $axisTypeId); - }) - ->groupBy('info_id', 'step') - ->get(); - -// $country = DB::select( -// "SELECT COUNT(*) as qty,info_id, step -// FROM safety_and_privacy where created_at BETWEEN '".$fromDate."' and '".$toDate."' -// GROUP BY info_id,step" -// ); + $country = DataTableFacade::run( + $countryQuery, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + allowedGroupBy: ['info_id', 'step'] + ); $countryTotalSum = 0; $countryData = [ 'name_fa' => 'کشوری', 'province_id' => -1, 'sum' => 0, - '89' => [ - '1' => 0, - '2' => 0, - '3' => 0, - ], - '90' => [ - '1' => 0, - '2' => 0, - '3' => 0, - ], - '91' => [ - '1' => 0, - '2' => 0, - '3' => 0, - ], + '89' => ['1' => 0, '2' => 0, '3' => 0,], + '90' => ['1' => 0, '2' => 0, '3' => 0,], + '91' => ['1' => 0, '2' => 0, '3' => 0,], ]; foreach ($country as $key => $value) { $countryTotalSum += $value->qty; $countryData[$value->info_id][$value->step] = $value->qty; $countryData["sum"] = $countryTotalSum; } + $activities[] = (object) $countryData; + $provinceQuery = Province::query()->selectRaw('province_id, province_fa, COUNT(*) as qty,info_id, step'); + $provinces = DataTableFacade::run( + $provinceQuery, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + allowedGroupBy: ['info_id', 'step', 'province_id', 'province_fa'] + ); - $provinces = SafetyAndPrivacy::query() - ->selectRaw('province_id, province_fa, COUNT(*) as qty,info_id, step') - ->whereBetween('created_at', [$fromDate, $toDate]) - ->when($axisTypeId, function ($query) use ($axisTypeId) { - $query->where('axis_type_id', '=', $axisTypeId); - }) - ->groupBy('info_id', 'step', 'province_id', 'province_fa') - ->get(); - -// $provinces = DB::select( -// "SELECT province_id, province_fa, COUNT(*) as qty,info_id, step -// FROM safety_and_privacy where created_at BETWEEN '".$fromDate."' and '".$toDate."' -// GROUP BY info_id,step,province_id,province_fa" -// ); - - foreach ($provinces as $value) { + foreach ($provinces as $value) + { $provinceId = $value->province_id; - - // Check if the province already exists in the activities array if (!isset($activities[$provinceId])) { $activities[$provinceId] = (object) [ 'province_id' => $provinceId, @@ -129,64 +101,33 @@ class SafetyAndPrivacyTableService '91' => ['1' => 0, '2' => 0, '3' => 0], ]; } - $activities[$provinceId]->{$value->info_id}[$value->step] = $value->qty; $activities[$provinceId]->sum += $value->qty; } - $activities = array_values($activities); - - return [ - 'activities' => $activities, - 'fromDate' => $fromDate, - 'toDate' => $toDate, - ]; + return array_values($activities); } public function provinceActivity(Request $request): array { - $fromDate = $request->from_date ? $request->from_date . ' 00:00:00' : now()->startOfDay()->toDateTimeString(); - $toDate = $request->date_to ? $request->date_to . ' 23:59:59' : now()->endOfDay()->toDateTimeString(); - $provinceId = $request->province_id; - $axisTypeId = $request->axis_type_id; $activities = []; - - $province = SafetyAndPrivacy::query() - ->selectRaw('COUNT(*) as qty,info_id, step') - ->where('province_id', '=', $provinceId) - ->whereBetween('created_at', [$fromDate, $toDate]) - ->when($axisTypeId, function ($query) use ($axisTypeId) { - $query->where('axis_type_id', '=', $axisTypeId); - }) - ->groupBy('info_id', 'step') - ->get(); - -// $province = DB::select(' -// SELECT COUNT(*) as qty,info_id, step -// FROM safety_and_privacy where province_id ='.$provinceId.' and created_at BETWEEN "'.$fromDate.'" and "'.$toDate.'" -// GROUP BY info_id,step -// '); + $provinceQuery = Province::query()->selectRaw('COUNT(*) as qty,info_id, step'); + $province = DataTableFacade::run( + $provinceQuery, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + allowedGroupBy: ['info_id', 'step'] + ); $provinceTotalSum = 0; $provinceData = [ 'name_fa' => 'استانی', 'edare_shahri_id' => -1, 'sum' => 0, - '89' => [ - '1' => 0, - '2' => 0, - '3' => 0, - ], - '90' => [ - '1' => 0, - '2' => 0, - '3' => 0, - ], - '91' => [ - '1' => 0, - '2' => 0, - '3' => 0, - ], + '89' => ['1' => 0, '2' => 0, '3' => 0,], + '90' => ['1' => 0, '2' => 0, '3' => 0,], + '91' => ['1' => 0, '2' => 0, '3' => 0,], ]; foreach ($province as $key => $value) { $provinceTotalSum += $value->qty; @@ -195,26 +136,18 @@ class SafetyAndPrivacyTableService } $activities[] = (object) $provinceData; - $cities = SafetyAndPrivacy::query() - ->selectRaw('edare_shahri_id, COUNT(*) as qty,info_id, step') - ->where('province_id', '=', $provinceId) - ->whereBetween('created_at', [$fromDate, $toDate]) - ->when($axisTypeId, function ($query) use ($axisTypeId) { - $query->where('axis_type_id', '=', $axisTypeId); - }) - ->groupBy('info_id', 'step', 'edare_shahri_id') - ->get(); + $citiesQuery = SafetyAndPrivacy::query()->selectRaw('edare_shahri_id, COUNT(*) as qty,info_id, step'); + $cities = DataTableFacade::run( + $citiesQuery, + $request, + allowedFilters: ['*'], + allowedSortings: ['*'], + allowedGroupBy: ['info_id', 'step', 'edare_shahri_id'] + ); -// $cities = DB::select(' -// SELECT edare_shahri_id, COUNT(*) as qty,info_id, step -// FROM safety_and_privacy where province_id ='.$provinceId.' and created_at BETWEEN "'.$fromDate.'" and "'.$toDate.'" -// GROUP BY info_id,step,edare_shahri_id -// '); - - foreach ($cities as $value) { + foreach ($cities as $value) + { $cityId = $value->edare_shahri_id; - - // Initialize data for each unique city if (!isset($activities[$cityId])) { $activities[$cityId] = (object) [ 'edare_shahri_id' => $cityId, @@ -229,12 +162,6 @@ class SafetyAndPrivacyTableService $activities[$cityId]->sum += $value->qty; } - $activities = array_values($activities); - - return [ - 'activities' => $activities, - 'fromDate' => $fromDate, - 'toDate' => $toDate, - ]; + return array_values($activities); } } diff --git a/app/Services/DataTable/DataTableInput.php b/app/Services/DataTable/DataTableInput.php index 8464e878..1bbe5200 100644 --- a/app/Services/DataTable/DataTableInput.php +++ b/app/Services/DataTable/DataTableInput.php @@ -22,6 +22,7 @@ class DataTableInput private array $rels, private array $allowedFilters, private array $allowedSortings, + private ?array $GroupBy, ) { } @@ -74,4 +75,9 @@ class DataTableInput { return $this->rels; } + + public function getGroupBy(): ?array + { + return $this->GroupBy; + } } diff --git a/app/Services/DataTable/DataTableService.php b/app/Services/DataTable/DataTableService.php index 647f6e44..442f6e48 100644 --- a/app/Services/DataTable/DataTableService.php +++ b/app/Services/DataTable/DataTableService.php @@ -13,6 +13,7 @@ class DataTableService protected array $allowedRelations; protected array $allowedSortings; protected array $allowedSelects; + protected array $allowedGroupBy; private int $totalRowCount; public function __construct( @@ -46,6 +47,12 @@ class DataTableService return $this; } + public function setAllowedGroupBy(array $allowedGroupBy): DataTableService + { + $this->allowedGroupBy = $allowedGroupBy; + return $this; + } + /** * Handle 'getData' operations * @return array @@ -88,7 +95,9 @@ class DataTableService foreach ($sorting as $sort){ $query = (new ApplySort($query, $sort))->apply(); } - + + $query = $this->applyGroupBy($query, $this->allowedGroupBy); + return $query; } @@ -101,6 +110,11 @@ class DataTableService return $query; } + protected function applyGroupBy(Builder $query, array $groupBy): Builder + { + return empty($groupBy) ? $query : $query->groupBy($groupBy); + } + protected function includeRelationsInQuery(Builder $query, array $rels): Builder { if (!empty($rels)) {