diff --git a/.config/psysh/psysh_history b/.config/psysh/psysh_history index d3dc184..441f57d 100644 --- a/.config/psysh/psysh_history +++ b/.config/psysh/psysh_history @@ -14,3 +14,6 @@ BigdataResume::generateResumeData(253,2025,"simbg"); exit BigdataResume::generateResumeData(253,2025,"simbg"); exit +Bigdataresume::generateResumeData(253,2025,'simbg'); +BigdataResume::generateResumeData(253,2025,'simbg'); +exit diff --git a/app/Http/Controllers/Api/RequestAssignmentController.php b/app/Http/Controllers/Api/RequestAssignmentController.php index bc9669a..61ed865 100644 --- a/app/Http/Controllers/Api/RequestAssignmentController.php +++ b/app/Http/Controllers/Api/RequestAssignmentController.php @@ -25,7 +25,17 @@ class RequestAssignmentController extends Controller // Build base query for counting (without relationships to avoid duplicates) $baseQuery = PbgTask::query(); - // Apply filters to base query + // Filter only valid data (is_valid = true) + $baseQuery->where('is_valid', true); + + // Apply year filter if provided (to match BigdataResume behavior) + if ($request->has('year') && !empty($request->get('year'))) { + $year = $request->get('year'); + $baseQuery->whereYear('task_created_at', $year); + Log::info('RequestAssignmentController year filter applied', ['year' => $year]); + } + + // Apply filters to base query (matching BigdataResume logic exactly) if ($request->has('filter') && !empty($request->get('filter'))) { $filter = strtolower(trim($request->get('filter'))); @@ -34,6 +44,7 @@ class RequestAssignmentController extends Controller switch ($filter) { case 'non-business': + // Match BigdataResume non-business logic exactly $baseQuery->where(function ($q) { $q->where(function ($q2) { $q2->where(function ($q3) { @@ -47,6 +58,7 @@ class RequestAssignmentController extends Controller break; case 'business': + // Match BigdataResume business logic exactly $baseQuery->where(function ($q) { $q->where(function ($q2) { $q2->whereRaw("LOWER(TRIM(function_type)) LIKE ?", ['%fungsi usaha%']) @@ -57,25 +69,35 @@ class RequestAssignmentController extends Controller break; case 'verified': + // Match BigdataResume verified logic exactly $baseQuery->whereIn("status", PbgTaskStatus::getVerified()); break; case 'non-verified': + // Match BigdataResume non-verified logic exactly $baseQuery->whereIn("status", PbgTaskStatus::getNonVerified()); break; case 'potention': + // Match BigdataResume potention logic exactly $baseQuery->whereIn("status", PbgTaskStatus::getPotention()); break; + case 'issuance-realization-pbg': + // Match BigdataResume issuance realization logic exactly $baseQuery->whereIn("status", PbgTaskStatus::getIssuanceRealizationPbg()); break; + case 'process-in-technical-office': + // Match BigdataResume process in technical office logic exactly $baseQuery->whereIn("status", PbgTaskStatus::getProcessInTechnicalOffice()); break; + case 'waiting-click-dpmptsp': + // Match BigdataResume waiting click DPMPTSP logic exactly $baseQuery->whereIn("status", PbgTaskStatus::getWaitingClickDpmptsp()); break; + default: // Log unrecognized filter for debugging Log::warning('Unrecognized filter value', ['filter' => $filter, 'original' => $request->get('filter')]); @@ -124,11 +146,18 @@ class RequestAssignmentController extends Controller Log::info('RequestAssignmentController final result', [ 'filter' => $request->get('filter'), 'search' => $request->get('search'), + 'year' => $request->get('year'), 'accurate_count' => $accurateCount, 'request_url' => $request->fullUrl(), 'all_params' => $request->all() ]); + // Cross-validation with BigdataResume logic (for debugging consistency) + if ($request->has('filter') && $request->has('year') && + !empty($request->get('filter')) && !empty($request->get('year'))) { + $this->validateConsistencyWithBigdataResume($request->get('filter'), $request->get('year'), $accurateCount); + } + // Additional logging for potention filter if ($request->get('filter') === 'potention') { $rejectedCount = PbgTask::whereIn('status', PbgTaskStatus::getRejected())->count(); @@ -141,7 +170,7 @@ class RequestAssignmentController extends Controller } // Also log to console for immediate debugging - if ($request->has('filter')) { + if ($request->has('filter') && !empty($request->get('filter'))) { error_log('RequestAssignment Filter Debug: ' . $request->get('filter') . ' -> Count: ' . $accurateCount); } @@ -243,4 +272,141 @@ class RequestAssignmentController extends Controller { // } + + /** + * Validate consistency with BigdataResume logic for debugging + */ + private function validateConsistencyWithBigdataResume(?string $filter, $year, int $actualCount) + { + try { + // Validate input parameters + if (empty($filter) || empty($year)) { + Log::info('Skipping consistency validation - empty filter or year', [ + 'filter' => $filter, + 'year' => $year + ]); + return; + } + + // Convert year to integer + $year = (int) $year; + if ($year <= 0) { + Log::warning('Invalid year provided for consistency validation', ['year' => $year]); + return; + } + + $bigdataResumeCount = null; + + // Calculate expected count using BigdataResume logic + switch ($filter) { + case 'verified': + $bigdataResumeCount = PbgTask::whereIn('status', PbgTaskStatus::getVerified()) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'non-verified': + $bigdataResumeCount = PbgTask::whereIn('status', PbgTaskStatus::getNonVerified()) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'business': + $bigdataResumeCount = PbgTask::where(function ($q) { + $q->where(function ($q2) { + $q2->whereRaw("LOWER(TRIM(function_type)) LIKE ?", ['%fungsi usaha%']) + ->orWhereRaw("LOWER(TRIM(function_type)) LIKE ?", ['%sebagai tempat usaha%']); + }) + ->whereIn("status", PbgTaskStatus::getNonVerified()); + }) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'non-business': + $bigdataResumeCount = PbgTask::where(function ($q) { + $q->where(function ($q2) { + $q2->where(function ($q3) { + $q3->whereRaw("LOWER(TRIM(function_type)) NOT LIKE ?", ['%fungsi usaha%']) + ->whereRaw("LOWER(TRIM(function_type)) NOT LIKE ?", ['%sebagai tempat usaha%']); + }) + ->orWhereNull('function_type'); + }) + ->whereIn("status", PbgTaskStatus::getNonVerified()); + }) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'potention': + $bigdataResumeCount = PbgTask::whereIn('status', PbgTaskStatus::getPotention()) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'waiting-click-dpmptsp': + $bigdataResumeCount = PbgTask::whereIn('status', PbgTaskStatus::getWaitingClickDpmptsp()) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'issuance-realization-pbg': + $bigdataResumeCount = PbgTask::whereIn('status', PbgTaskStatus::getIssuanceRealizationPbg()) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + case 'process-in-technical-office': + $bigdataResumeCount = PbgTask::whereIn('status', PbgTaskStatus::getProcessInTechnicalOffice()) + ->where('is_valid', true) + ->whereYear('task_created_at', $year) + ->count(); + break; + + default: + Log::info('Unknown filter for consistency validation', [ + 'filter' => $filter, + 'year' => $year + ]); + return; + } + + if ($bigdataResumeCount !== null) { + $isConsistent = ($actualCount === $bigdataResumeCount); + + Log::info('RequestAssignment vs BigdataResume consistency check', [ + 'filter' => $filter, + 'year' => $year, + 'request_assignment_count' => $actualCount, + 'bigdata_resume_count' => $bigdataResumeCount, + 'is_consistent' => $isConsistent, + 'difference' => $actualCount - $bigdataResumeCount + ]); + + if (!$isConsistent) { + Log::warning('INCONSISTENCY DETECTED between RequestAssignment and BigdataResume', [ + 'filter' => $filter, + 'year' => $year, + 'request_assignment_count' => $actualCount, + 'bigdata_resume_count' => $bigdataResumeCount, + 'difference' => $actualCount - $bigdataResumeCount + ]); + } + } + + } catch (\Exception $e) { + Log::error('Error in consistency validation', [ + 'error' => $e->getMessage(), + 'filter' => $filter, + 'year' => $year + ]); + } + } } diff --git a/app/Models/BigdataResume.php b/app/Models/BigdataResume.php index 965937b..d33dfcd 100644 --- a/app/Models/BigdataResume.php +++ b/app/Models/BigdataResume.php @@ -47,22 +47,29 @@ class BigdataResume extends Model public static function generateResumeData($import_datasource_id, $year, $resume_type){ // Get accurate counts without joins to avoid duplicates from multiple retributions + // Filter only valid data (is_valid = true) $verified_count = PbgTask::whereIn('status', PbgTaskStatus::getVerified()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); $non_verified_count = PbgTask::whereIn('status', PbgTaskStatus::getNonVerified()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); $waiting_click_dpmptsp_count = PbgTask::whereIn('status', PbgTaskStatus::getWaitingClickDpmptsp()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); $issuance_realization_pbg_count = PbgTask::whereIn('status', PbgTaskStatus::getIssuanceRealizationPbg()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); $process_in_technical_office_count = PbgTask::whereIn('status', PbgTaskStatus::getProcessInTechnicalOffice()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); $potention_count = PbgTask::whereIn('status', PbgTaskStatus::getPotention()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); @@ -74,6 +81,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); @@ -88,6 +96,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->count(); @@ -101,6 +110,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->whereExists(function ($query) { $query->select(DB::raw(1)) @@ -133,6 +143,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->whereExists(function ($query) { $query->select(DB::raw(1)) @@ -168,6 +179,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->whereExists(function ($query) { $query->select(DB::raw(1)) @@ -203,6 +215,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->whereExists(function ($query) { $query->select(DB::raw(1)) @@ -238,6 +251,7 @@ class BigdataResume extends Model }) ->whereIn("status", PbgTaskStatus::getNonVerified()); }) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->whereExists(function ($query) { $query->select(DB::raw(1)) @@ -264,6 +278,7 @@ class BigdataResume extends Model // Debug: Check if there are non-verified tasks and their retribution data $debug_non_verified = PbgTask::whereIn('status', PbgTaskStatus::getNonVerified()) + ->where('is_valid', true) ->whereYear('task_created_at', $year) ->with('pbg_task_retributions') ->get(); @@ -283,6 +298,7 @@ class BigdataResume extends Model // Get sum values using proper aggregation to handle multiple retributions $stats = PbgTask::leftJoin('pbg_task_retributions as ptr', 'pbg_task.uuid', '=', 'ptr.pbg_task_uid') + ->where('pbg_task.is_valid', true) ->whereYear('pbg_task.task_created_at', $year) ->selectRaw(" SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getVerified()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS verified_total, diff --git a/resources/js/pbg-task/index.js b/resources/js/pbg-task/index.js index b2888a6..1c9e4a8 100644 --- a/resources/js/pbg-task/index.js +++ b/resources/js/pbg-task/index.js @@ -43,19 +43,29 @@ class PbgTasks { handleFilterDatatable() { const form = document.getElementById("filter-form"); const filterSelect = document.getElementById("filter-select"); + const yearSelect = document.getElementById("year-select"); + const resetBtn = document.getElementById("reset-filter"); const urlParams = new URLSearchParams(window.location.search); const initialFilter = urlParams.get("filter") || ""; + const initialYear = urlParams.get("year") || "2025"; // Default to 2025 - this.initTableRequestAssignment(initialFilter); // Initial load with query param + // Set initial year if not in URL + if (!urlParams.get("year")) { + yearSelect.value = "2025"; + } + + this.initTableRequestAssignment(initialFilter, initialYear); // Initial load with query params form.addEventListener("submit", (e) => { e.preventDefault(); const selectedFilter = filterSelect.value; + const selectedYear = yearSelect.value; const params = new URLSearchParams(window.location.search); params.set("filter", selectedFilter); + params.set("year", selectedYear); // Update the URL without reloading window.history.replaceState( @@ -64,12 +74,27 @@ class PbgTasks { `${location.pathname}?${params}` ); - // Call the method again with the selected filter - this.initTableRequestAssignment(selectedFilter); + // Call the method again with the selected filter and year + this.initTableRequestAssignment(selectedFilter, selectedYear); + }); + + // Handle reset button + resetBtn.addEventListener("click", (e) => { + e.preventDefault(); + + // Reset form values + filterSelect.value = ""; + yearSelect.value = "2025"; + + // Clear URL parameters + window.history.replaceState({}, "", location.pathname); + + // Reload table with default values + this.initTableRequestAssignment("", "2025"); }); } - initTableRequestAssignment(filterValue = "") { + initTableRequestAssignment(filterValue = "", yearValue = "2025") { const urlBase = `${GlobalConfig.apiHost}/api/request-assignments`; // Ambil token @@ -179,7 +204,7 @@ class PbgTasks { }, sort: true, server: { - url: `${urlBase}?filter=${filterValue}`, + url: `${urlBase}?filter=${filterValue}&year=${yearValue}`, credentials: "include", headers: { Authorization: `Bearer ${token}`, @@ -365,7 +390,18 @@ class PbgTasks { self.toastMessage.innerText = "File uploaded successfully!"; self.toast.show(); - self.initTableRequestAssignment(); + + // Get current filter and year values to refresh table + const currentFilter = + document.getElementById("filter-select").value || + ""; + const currentYear = + document.getElementById("year-select").value || + "2025"; + self.initTableRequestAssignment( + currentFilter, + currentYear + ); }); dz.on("error", (file, message) => { diff --git a/resources/views/dashboards/bigdata.blade.php b/resources/views/dashboards/bigdata.blade.php index c0aeffe..378159a 100644 --- a/resources/views/dashboards/bigdata.blade.php +++ b/resources/views/dashboards/bigdata.blade.php @@ -58,7 +58,7 @@ 'document_id' => 'chart-total-potensi', 'visible_small_circle' => true, 'style' => 'left:400px;top:150px;', - 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'potention']) + 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'potention', 'year' => date('Y')]) ]) @endcomponent @@ -82,16 +82,7 @@