fix pbg task add toggle and rab krk dlh

This commit is contained in:
arifal
2025-08-19 13:00:40 +07:00
parent d7e9f44b20
commit 2cbc4172da
17 changed files with 894 additions and 239 deletions

View File

@@ -9,3 +9,8 @@ exit
(new App\Jobs\ScrapingDataJob())->handle(); (new App\Jobs\ScrapingDataJob())->handle();
(new App\Jobs\ScrapingDataJob())->handle(); (new App\Jobs\ScrapingDataJob())->handle();
exit exit
exit
BigdataResume::generateResumeData(253,2025,"simbg");
exit
BigdataResume::generateResumeData(253,2025,"simbg");
exit

View File

@@ -0,0 +1,17 @@
0 verbose cli /usr/bin/node /usr/bin/npm
1 info using npm@10.8.2
2 info using node@v18.20.8
3 silly config load:file:/usr/lib/node_modules/npm/npmrc
4 silly config load:file:/var/www/.npmrc
5 silly config load:file:/usr/etc/npmrc
6 verbose title npm run build
7 verbose argv "run" "build"
8 verbose logfile logs-max:10 dir:/var/www/.npm/_logs/2025-08-19T05_29_08_290Z-
9 verbose logfile /var/www/.npm/_logs/2025-08-19T05_29_08_290Z-debug-0.log
10 silly logfile done cleaning log files
11 verbose cwd /var/www
12 verbose os Linux 6.6.87.2-microsoft-standard-WSL2
13 verbose node v18.20.8
14 verbose npm v10.8.2
15 verbose exit 0
16 info ok

View File

@@ -42,11 +42,11 @@ class BigDataResumeController extends Controller
} }
$data_settings = DataSetting::all(); $data_settings = DataSetting::all();
if($data_settings->isEmpty()){ $target_pad = 0;
return response()->json(['message' => 'No data setting found']); if($data_settings->where('key', 'TARGET_PAD')->first()){
$target_pad = floatval($data_settings->where('key', 'TARGET_PAD')->first()->value ?? 0);
} }
$target_pad = floatval(optional($data_settings->where('key', 'TARGET_PAD')->first())->value);
$realisasi_terbit_pbg_sum = $big_data_resume->issuance_realization_pbg_sum; $realisasi_terbit_pbg_sum = $big_data_resume->issuance_realization_pbg_sum;
$realisasi_terbit_pbg_count = $big_data_resume->issuance_realization_pbg_count; $realisasi_terbit_pbg_count = $big_data_resume->issuance_realization_pbg_count;
$menunggu_klik_dpmptsp_sum = $big_data_resume->waiting_click_dpmptsp_sum; $menunggu_klik_dpmptsp_sum = $big_data_resume->waiting_click_dpmptsp_sum;
@@ -107,7 +107,7 @@ class BigDataResumeController extends Controller
$business_krk_count = $big_data_resume->business_krk_count; $business_krk_count = $big_data_resume->business_krk_count;
$non_business_rab_count = $big_data_resume->non_business_rab_count; $non_business_rab_count = $big_data_resume->non_business_rab_count;
$non_business_krk_count = $big_data_resume->non_business_krk_count; $non_business_krk_count = $big_data_resume->non_business_krk_count;
$non_business_dlh_count = $big_data_resume->non_business_dlh_count; $business_dlh_count = $big_data_resume->business_dlh_count;
$result = [ $result = [
'target_pad' => [ 'target_pad' => [
@@ -167,7 +167,7 @@ class BigDataResumeController extends Controller
'business_krk_count' => $business_krk_count, 'business_krk_count' => $business_krk_count,
'non_business_rab_count' => $non_business_rab_count, 'non_business_rab_count' => $non_business_rab_count,
'non_business_krk_count' => $non_business_krk_count, 'non_business_krk_count' => $non_business_krk_count,
'non_business_dlh_count' => $non_business_dlh_count 'business_dlh_count' => $business_dlh_count
]; ];
return response()->json($result); return response()->json($result);
}catch(\Exception $e){ }catch(\Exception $e){
@@ -336,9 +336,15 @@ class BigDataResumeController extends Controller
return $pdf->download('laporan-pimpinan.pdf'); return $pdf->download('laporan-pimpinan.pdf');
} }
private function response_empty_resume(){ private function response_empty_resume(){
$data_settings = DataSetting::all();
$target_pad = 0;
if($data_settings->where('key', 'TARGET_PAD')->first()){
$target_pad = floatval($data_settings->where('key', 'TARGET_PAD')->first()->value ?? 0);
}
$result = [ $result = [
'target_pad' => [ 'target_pad' => [
'sum' => 0, 'sum' => $target_pad,
'percentage' => 100, 'percentage' => 100,
], ],
'tata_ruang' => [ 'tata_ruang' => [

View File

@@ -132,39 +132,48 @@ class PbgTaskController extends Controller
} }
$validated = $request->validate([ $validated = $request->validate([
'name' => 'required|string|max:255', 'name' => 'nullable|string|max:255',
'owner_name' => 'required|string|max:255', 'owner_name' => 'nullable|string|max:255',
'application_type' => ['nullable', new Enum(PbgTaskApplicationTypes::class)], 'application_type' => ['nullable', new Enum(PbgTaskApplicationTypes::class)],
'condition' => 'required|string|max:255', 'condition' => 'nullable|string|max:255',
'registration_number' => 'required|string|max:255', 'registration_number' => 'nullable|string|max:255',
'document_number' => 'required|string|max:255', 'document_number' => 'nullable|string|max:255',
'status' => ['nullable', new Enum(PbgTaskStatus::class)], 'status' => ['nullable', new Enum(PbgTaskStatus::class)],
'address' => 'required|string|max:255', 'address' => 'nullable|string|max:255',
'slf_status_name' => 'nullable|string|max:255', 'slf_status_name' => 'nullable|string|max:255',
'function_type' => 'required|string|max:255', 'function_type' => 'nullable|string|max:255',
'consultation_type' => 'required|string|max:255', 'consultation_type' => 'nullable|string|max:255',
'due_date' => 'nullable|date|after_or_equal:today', 'due_date' => 'nullable|date',
'is_valid' => 'nullable|boolean',
]); ]);
$statusLabel = $validated['status'] !== null ? PbgTaskStatus::getLabel($validated['status']) : null; $statusLabel = $validated['status'] !== null ? PbgTaskStatus::getLabel($validated['status']) : null;
$applicationLabel = $validated['application_type'] !== null ? PbgTaskApplicationTypes::getLabel($validated['application_type']) : null; $applicationLabel = $validated['application_type'] !== null ? PbgTaskApplicationTypes::getLabel($validated['application_type']) : null;
$pbg_task->update([ // Prepare update data - only include fields that are actually provided
'name' => $validated['name'], $updateData = [];
'owner_name' => $validated['owner_name'],
'application_type' => $validated['application_type'], foreach ($validated as $key => $value) {
'application_type_name' => $applicationLabel, // Automatically set application_type_name if ($value !== null || $request->has($key)) {
'condition' => $validated['condition'], $updateData[$key] = $value;
'registration_number' => $validated['registration_number'], }
'document_number' => $validated['document_number'], }
'status' => $validated['status'],
'status_name' => $statusLabel, // Automatically set status_name // Handle special cases for labels
'address' => $validated['address'], if (isset($updateData['status'])) {
'slf_status_name' => $validated['slf_status_name'], $updateData['status_name'] = $statusLabel;
'function_type' => $validated['function_type'], }
'consultation_type' => $validated['consultation_type'],
'due_date' => $validated['due_date'], if (isset($updateData['application_type'])) {
]); $updateData['application_type_name'] = $applicationLabel;
}
// Handle is_valid specifically
if ($request->has('is_valid')) {
$updateData['is_valid'] = $validated['is_valid'];
}
$pbg_task->update($updateData);
return response()->json([ return response()->json([
"success"=> true, "success"=> true,
"message"=> "Data berhasil diubah", "message"=> "Data berhasil diubah",

View File

@@ -34,9 +34,9 @@ class BigdataResume extends Model
'process_in_technical_office_sum', 'process_in_technical_office_sum',
'business_rab_count', 'business_rab_count',
'business_krk_count', 'business_krk_count',
'business_dlh_count',
'non_business_rab_count', 'non_business_rab_count',
'non_business_krk_count', 'non_business_krk_count',
'non_business_dlh_count',
'resume_type', 'resume_type',
]; ];
@@ -155,6 +155,41 @@ class BigdataResume extends Model
') ')
->value('total_count') ?? 0; ->value('total_count') ?? 0;
// Non-Business DLH count - for each non-business task with data_type=5:
// if any status != 1 then return 1, if all status = 1 then return 0, then sum all
$business_dlh_count = DB::table('pbg_task')
->where(function ($q) {
$q->where(function ($q2) {
$q2->where(function ($q3) {
$q3->whereRaw("LOWER(TRIM(function_type)) LIKE ?", ['%fungsi usaha%'])
->whereRaw("LOWER(TRIM(function_type)) LIKE ?", ['%sebagai tempat usaha%']);
})
->orWhereNull('function_type');
})
->whereIn("status", PbgTaskStatus::getNonVerified());
})
->whereYear('task_created_at', $year)
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('pbg_task_detail_data_lists')
->whereColumn('pbg_task_detail_data_lists.pbg_task_uuid', 'pbg_task.uuid')
->where('pbg_task_detail_data_lists.data_type', 5);
})
->selectRaw('
SUM(
CASE
WHEN EXISTS (
SELECT 1 FROM pbg_task_detail_data_lists ptddl
WHERE ptddl.pbg_task_uuid = pbg_task.uuid
AND ptddl.data_type = 5
AND ptddl.status != 1
) THEN 1
ELSE 0
END
) as total_count
')
->value('total_count') ?? 0;
// Non-Business RAB count - for each non-business task with data_type=3: // Non-Business RAB count - for each non-business task with data_type=3:
// if any status != 1 then return 1, if all status = 1 then return 0, then sum all // if any status != 1 then return 1, if all status = 1 then return 0, then sum all
$non_business_rab_count = DB::table('pbg_task') $non_business_rab_count = DB::table('pbg_task')
@@ -225,61 +260,55 @@ class BigdataResume extends Model
') ')
->value('total_count') ?? 0; ->value('total_count') ?? 0;
// Non-Business DLH count - for each non-business task with data_type=5:
// if any status != 1 then return 1, if all status = 1 then return 0, then sum all
$non_business_dlh_count = DB::table('pbg_task') // Debug: Check if there are non-verified tasks and their retribution data
->where(function ($q) { $debug_non_verified = PbgTask::whereIn('status', PbgTaskStatus::getNonVerified())
$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());
})
->whereYear('task_created_at', $year) ->whereYear('task_created_at', $year)
->whereExists(function ($query) { ->with('pbg_task_retributions')
$query->select(DB::raw(1)) ->get();
->from('pbg_task_detail_data_lists')
->whereColumn('pbg_task_detail_data_lists.pbg_task_uuid', 'pbg_task.uuid') \Log::info('Non-verified tasks debug', [
->where('pbg_task_detail_data_lists.data_type', 5); 'year' => $year,
}) 'non_verified_statuses' => PbgTaskStatus::getNonVerified(),
->selectRaw(' 'tasks_count' => $debug_non_verified->count(),
SUM( 'tasks_with_retribution' => $debug_non_verified->filter(fn($task) => $task->pbg_task_retributions)->count(),
CASE 'sample_retribution_values' => $debug_non_verified->take(3)->map(fn($task) => [
WHEN EXISTS ( 'uuid' => $task->uuid,
SELECT 1 FROM pbg_task_detail_data_lists ptddl 'status' => $task->status,
WHERE ptddl.pbg_task_uuid = pbg_task.uuid 'has_retribution' => !is_null($task->pbg_task_retributions),
AND ptddl.data_type = 5 'retribution_value' => $task->pbg_task_retributions?->nilai_retribusi_bangunan ?? 'NULL'
AND ptddl.status != 1 ])
) THEN 1 ]);
ELSE 0
END
) as total_count
')
->value('total_count') ?? 0;
// Get sum values using proper aggregation to handle multiple retributions // 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') $stats = PbgTask::leftJoin('pbg_task_retributions as ptr', 'pbg_task.uuid', '=', 'ptr.pbg_task_uid')
->whereYear('pbg_task.task_created_at', $year) ->whereYear('pbg_task.task_created_at', $year)
->selectRaw(" ->selectRaw("
SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getVerified()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS verified_total, SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getVerified()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS verified_total,
SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS non_verified_total, SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS non_verified_total,
SUM(CASE WHEN (LOWER(TRIM(pbg_task.function_type)) LIKE '%fungsi usaha%' SUM(CASE WHEN (LOWER(TRIM(pbg_task.function_type)) LIKE '%fungsi usaha%'
OR LOWER(TRIM(pbg_task.function_type)) LIKE '%sebagai tempat usaha%') OR LOWER(TRIM(pbg_task.function_type)) LIKE '%sebagai tempat usaha%')
AND pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS business_total, AND pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS business_total,
SUM(CASE WHEN (LOWER(TRIM(pbg_task.function_type)) NOT LIKE '%fungsi usaha%' SUM(CASE WHEN (LOWER(TRIM(pbg_task.function_type)) NOT LIKE '%fungsi usaha%'
AND LOWER(TRIM(pbg_task.function_type)) NOT LIKE '%sebagai tempat usaha%' AND LOWER(TRIM(pbg_task.function_type)) NOT LIKE '%sebagai tempat usaha%'
AND pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).")) AND pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified())."))
OR (pbg_task.function_type IS NULL AND pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).")) THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS non_business_total, OR (pbg_task.function_type IS NULL AND pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).")) THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS non_business_total,
SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getWaitingClickDpmptsp()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS waiting_click_dpmptsp_total, SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getWaitingClickDpmptsp()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS waiting_click_dpmptsp_total,
SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getIssuanceRealizationPbg()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS issuance_realization_pbg_total, SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getIssuanceRealizationPbg()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS issuance_realization_pbg_total,
SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getProcessInTechnicalOffice()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS process_in_technical_office_total, SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getProcessInTechnicalOffice()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS process_in_technical_office_total,
SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getPotention()).") THEN ptr.nilai_retribusi_bangunan ELSE 0 END) AS potention_total SUM(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getPotention()).") THEN COALESCE(ptr.nilai_retribusi_bangunan, 0) ELSE 0 END) AS potention_total,
COUNT(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).") THEN 1 END) AS non_verified_tasks_count,
COUNT(CASE WHEN pbg_task.status in (".implode(',', PbgTaskStatus::getNonVerified()).") AND ptr.nilai_retribusi_bangunan IS NOT NULL THEN 1 END) AS non_verified_with_retribution_count
") ")
->first(); ->first();
\Log::info('Stats calculation result', [
'non_verified_total' => $stats->non_verified_total ?? 'NULL',
'non_verified_tasks_count' => $stats->non_verified_tasks_count ?? 'NULL',
'non_verified_with_retribution_count' => $stats->non_verified_with_retribution_count ?? 'NULL'
]);
$service_google_sheet = app(ServiceGoogleSheet::class); $service_google_sheet = app(ServiceGoogleSheet::class);
return self::create([ return self::create([
@@ -305,9 +334,9 @@ class BigdataResume extends Model
'process_in_technical_office_sum' => $stats->process_in_technical_office_total ?? 0.00, 'process_in_technical_office_sum' => $stats->process_in_technical_office_total ?? 0.00,
'business_rab_count' => $business_rab_count, 'business_rab_count' => $business_rab_count,
'business_krk_count' => $business_krk_count, 'business_krk_count' => $business_krk_count,
'business_dlh_count' => $business_dlh_count,
'non_business_rab_count' => $non_business_rab_count, 'non_business_rab_count' => $non_business_rab_count,
'non_business_krk_count' => $non_business_krk_count, 'non_business_krk_count' => $non_business_krk_count,
'non_business_dlh_count' => $non_business_dlh_count,
'resume_type' => $resume_type, 'resume_type' => $resume_type,
]); ]);
} }

View File

@@ -27,7 +27,8 @@ class PbgTask extends Model
'consultation_type', 'consultation_type',
'due_date', 'due_date',
'land_certificate_phase', 'land_certificate_phase',
'task_created_at' 'task_created_at',
'is_valid'
]; ];
public function pbg_task_retributions(){ public function pbg_task_retributions(){

View File

@@ -143,54 +143,208 @@ class PbgTaskDetail extends Model
/**
* Helper method to clean and convert latitude/longitude values
*/
private static function cleanCoordinate($value): ?float
{
if ($value === null || $value === '' || $value === '?' || $value === '-') {
return null;
}
// Convert to string and trim whitespace
$stringValue = trim((string) $value);
// Check for common invalid values
if (in_array($stringValue, ['', '?', '-', 'null', 'NULL', 'N/A', '0,'], true)) {
return null;
}
// Remove degree symbol and other non-numeric characters except minus and decimal point
$cleaned = preg_replace('/[^\d.-]/', '', $stringValue);
// Check if cleaned value is empty or just a hyphen
if ($cleaned === '' || $cleaned === '-' || $cleaned === '.') {
return null;
}
// Validate if it's a valid number and within reasonable coordinate bounds
if (is_numeric($cleaned)) {
$coordinate = (float) $cleaned;
// Basic validation for reasonable coordinate ranges
// Latitude: -90 to 90, Longitude: -180 to 180
if ($coordinate >= -180 && $coordinate <= 180) {
return $coordinate;
}
}
return null;
}
/**
* Helper method to clean and convert integer values
*/
private static function cleanIntegerValue($value): int
{
if ($value === null || $value === '' || $value === '?') {
return 0;
}
// Convert to string and trim whitespace
$stringValue = trim((string) $value);
// Check for common invalid values
if (in_array($stringValue, ['', '?', '-', 'null', 'NULL', 'N/A'], true)) {
return 0;
}
// Remove any non-numeric characters except minus
$cleaned = preg_replace('/[^\d-]/', '', $stringValue);
// Check if cleaned value is empty or just invalid characters
if ($cleaned === '' || $cleaned === '-') {
return 0;
}
// Validate if it's a valid number
if (is_numeric($cleaned)) {
return (int) $cleaned;
}
return 0;
}
/**
* Helper method to clean and convert numeric values
*/
private static function cleanNumericValue($value, bool $nullable = false): ?float
{
if ($value === null || $value === '' || $value === '?') {
return $nullable ? null : 0;
}
// Convert to string and trim whitespace
$stringValue = trim((string) $value);
// Check for common invalid values
if (in_array($stringValue, ['', '?', '-', 'null', 'NULL', 'N/A'], true)) {
return $nullable ? null : 0;
}
// Remove any non-numeric characters except minus and decimal point
$cleaned = preg_replace('/[^\d.-]/', '', $stringValue);
// Check if cleaned value is empty or just invalid characters
if ($cleaned === '' || $cleaned === '-' || $cleaned === '.') {
return $nullable ? null : 0;
}
// Validate if it's a valid number
if (is_numeric($cleaned)) {
return (float) $cleaned;
}
return $nullable ? null : 0;
}
/**
* Helper method to handle date parsing with fallback
*/
private static function parseDate($date): ?string
{
if (!$date || $date === '?' || $date === 'null') {
return null;
}
try {
return Carbon::parse($date)->format('Y-m-d');
} catch (\Exception $e) {
return null;
}
}
/**
* Helper method to handle datetime parsing with fallback
*/
private static function parseDateTime($datetime): ?string
{
if (!$datetime || $datetime === '?' || $datetime === 'null') {
return null;
}
try {
return Carbon::parse($datetime)->format('Y-m-d H:i:s');
} catch (\Exception $e) {
return null;
}
}
/** /**
* Create or update PbgTaskDetail from API response * Create or update PbgTaskDetail from API response
*/ */
public static function createFromApiResponse(array $data, string $pbgTaskUuid): self public static function createFromApiResponse(array $data, string $pbgTaskUuid): self
{ {
$detailData = [ $detailData = [
// Foreign key relationship - string, required
'pbg_task_uid' => $pbgTaskUuid, 'pbg_task_uid' => $pbgTaskUuid,
'uid' => $data['uid'] ?? null,
'nik' => $data['nik'] ?? null, // Basic information
'type_card' => $data['type_card'] ?? null, 'uid' => $data['uid'] ?? "N/A", // string, unique, required
'ownership' => $data['ownership'] ?? null, 'nik' => isset($data['nik']) && $data['nik'] !== '' && $data['nik'] !== '?' ? $data['nik'] : null, // string, nullable
'owner_name' => $data['owner_name'] ?? null, 'type_card' => isset($data['type_card']) && $data['type_card'] !== '' && $data['type_card'] !== '?' ? $data['type_card'] : null, // string, nullable
'ward_id' => $data['ward_id'] ?? null, 'ownership' => $data['ownership'] ?? null, // string, nullable
'ward_name' => $data['ward_name'] ?? null, 'owner_name' => $data['owner_name'] ?? "N/A", // string, required
'district_id' => $data['district_id'] ?? null,
'district_name' => $data['district_name'] ?? null, // Owner location information - all required
'regency_id' => $data['regency_id'] ?? null, 'ward_id' => self::cleanIntegerValue($data['ward_id'] ?? 0), // bigInteger, required
'regency_name' => $data['regency_name'] ?? null, 'ward_name' => $data['ward_name'] ?? "N/A", // string, required
'province_id' => $data['province_id'] ?? null, 'district_id' => self::cleanIntegerValue($data['district_id'] ?? 0), // integer, required
'province_name' => $data['province_name'] ?? null, 'district_name' => $data['district_name'] ?? "N/A", // string, required
'address' => $data['address'] ?? null, 'regency_id' => self::cleanIntegerValue($data['regency_id'] ?? 0), // integer, required
'owner_email' => $data['owner_email'] ?? null, 'regency_name' => $data['regency_name'] ?? "N/A", // string, required
'owner_phone' => $data['owner_phone'] ?? null, 'province_id' => self::cleanIntegerValue($data['province_id'] ?? 0), // integer, required
'user' => $data['user'] ?? null, 'province_name' => $data['province_name'] ?? "N/A", // string, required
'name' => $data['name'] ?? null, 'address' => $data['address'] ?? "N/A", // text, required
'email' => $data['email'] ?? null,
'phone' => $data['phone'] ?? null, // Owner contact information - required
'user_nik' => $data['user_nik'] ?? null, 'owner_email' => $data['owner_email'] ?? "N/A", // string, required
'user_province_id' => $data['user_province_id'] ?? null, 'owner_phone' => $data['owner_phone'] ?? "N/A", // string, required
'user_province_name' => $data['user_province_name'] ?? null,
'user_regency_id' => $data['user_regency_id'] ?? null, // User information - all required
'user_regency_name' => $data['user_regency_name'] ?? null, 'user' => self::cleanIntegerValue($data['user'] ?? 0), // integer, required
'user_district_id' => $data['user_district_id'] ?? null, 'name' => $data['name'] ?? "N/A", // string, required
'user_district_name' => $data['user_district_name'] ?? null, 'email' => $data['email'] ?? "N/A", // string, required
'user_address' => $data['user_address'] ?? null, 'phone' => $data['phone'] ?? "N/A", // string, required
'status' => $data['status'] ?? null, 'user_nik' => $data['user_nik'] ?? "N/A", // string, required
'status_name' => $data['status_name'] ?? null,
'slf_status' => $data['slf_status'] ?? null, // User location information - all required
'slf_status_name' => $data['slf_status_name'] ?? null, 'user_province_id' => self::cleanIntegerValue($data['user_province_id'] ?? 0), // integer, required
'sppst_status' => $data['sppst_status'] ?? null, 'user_province_name' => $data['user_province_name'] ?? "N/A", // string, required
'sppst_file' => $data['sppst_file'] ?? null, 'user_regency_id' => self::cleanIntegerValue($data['user_regency_id'] ?? 0), // integer, required
'sppst_status_name' => $data['sppst_status_name'] ?? null, 'user_regency_name' => $data['user_regency_name'] ?? "N/A", // string, required
'file_pbg' => $data['file_pbg'] ?? null, 'user_district_id' => self::cleanIntegerValue($data['user_district_id'] ?? 0), // integer, required
'file_pbg_date' => isset($data['file_pbg_date']) ? Carbon::parse($data['file_pbg_date'])->format('Y-m-d') : null, 'user_district_name' => $data['user_district_name'] ?? "N/A", // string, required
'due_date' => isset($data['due_date']) ? Carbon::parse($data['due_date'])->format('Y-m-d') : null, 'user_address' => $data['user_address'] ?? "N/A", // text, required
'start_date' => isset($data['start_date']) ? Carbon::parse($data['start_date'])->format('Y-m-d') : null,
'document_number' => $data['document_number'] ?? null, // Status information
'registration_number' => $data['registration_number'] ?? null, 'status' => self::cleanIntegerValue($data['status'] ?? 0), // integer, required
'status_name' => $data['status_name'] ?? "N/A", // string, required
'slf_status' => isset($data['slf_status']) && is_numeric($data['slf_status']) ? (int) $data['slf_status'] : null, // integer, nullable
'slf_status_name' => $data['slf_status_name'] ?? null, // string, nullable
'sppst_status' => self::cleanIntegerValue($data['sppst_status'] ?? 0), // integer, required
'sppst_file' => $data['sppst_file'] ?? null, // string, nullable
'sppst_status_name' => $data['sppst_status_name'] ?? "N/A", // string, required
// Files and documents
'file_pbg' => $data['file_pbg'] ?? null, // string, nullable
'file_pbg_date' => self::parseDate($data['file_pbg_date'] ?? null), // date, nullable
'due_date' => self::parseDate($data['due_date'] ?? null), // date, nullable
'start_date' => self::parseDate($data['start_date'] ?? null) ?? now()->format('Y-m-d'), // date, required
'document_number' => $data['document_number'] ?? null, // string, nullable
'registration_number' => $data['registration_number'] ?? "N/A", // string, required
// Application information - all nullable
'function_type' => $data['function_type'] ?? null, 'function_type' => $data['function_type'] ?? null,
'application_type' => $data['application_type'] ?? null, 'application_type' => $data['application_type'] ?? null,
'application_type_name' => $data['application_type_name'] ?? null, 'application_type_name' => $data['application_type_name'] ?? null,
@@ -198,52 +352,74 @@ class PbgTaskDetail extends Model
'condition' => $data['condition'] ?? null, 'condition' => $data['condition'] ?? null,
'prototype' => $data['prototype'] ?? null, 'prototype' => $data['prototype'] ?? null,
'permanency' => $data['permanency'] ?? null, 'permanency' => $data['permanency'] ?? null,
'building_type' => $data['building_type'] ?? null,
// Building information - all nullable
'building_type' => isset($data['building_type']) && is_numeric($data['building_type']) ? (int) $data['building_type'] : null, // integer, nullable
'building_type_name' => $data['building_type_name'] ?? null, 'building_type_name' => $data['building_type_name'] ?? null,
'building_purpose' => $data['building_purpose'] ?? null, 'building_purpose' => $data['building_purpose'] ?? null,
'building_use' => $data['building_use'] ?? null, 'building_use' => $data['building_use'] ?? null,
'occupancy' => $data['occupancy'] ?? null, 'occupancy' => $data['occupancy'] ?? null,
'name_building' => $data['name_building'] ?? null, 'name_building' => $data['name_building'] ?? null,
'total_area' => $data['total_area'] ?? null,
'area' => $data['area'] ?? null, // Building dimensions and specifications
'area_type' => $data['area_type'] ?? null, 'total_area' => self::cleanNumericValue($data['total_area'] ?? 0), // decimal(10,2), required
'height' => $data['height'] ?? null, 'area' => self::cleanNumericValue($data['area'] ?? null, true), // decimal(10,2), nullable
'floor' => $data['floor'] ?? null, 'area_type' => $data['area_type'] ?? null, // string, nullable
'floor_area' => $data['floor_area'] ?? 0, 'height' => self::cleanNumericValue($data['height'] ?? 0), // decimal(8,2), required
'basement' => $data['basement'] ?? null, 'floor' => self::cleanIntegerValue($data['floor'] ?? 0), // integer, required
'basement_height' => $data['basement_height'] ?? 0, 'floor_area' => self::cleanNumericValue($data['floor_area'] ?? null, true), // decimal(10,2), nullable
'basement_area' => $data['basement_area'] ?? 0, 'basement' => isset($data['basement']) && $data['basement'] !== '' && $data['basement'] !== '?' ? $data['basement'] : null, // string, nullable
'unit' => $data['unit'] ?? null, 'basement_height' => self::cleanNumericValue($data['basement_height'] ?? null, true), // decimal(8,2), nullable
'prev_retribution' => $data['prev_retribution'] ?? 0, 'basement_area' => self::cleanNumericValue($data['basement_area'] ?? 0), // decimal(10,2), required
'prev_pbg' => $data['prev_pbg'] ?? null, 'unit' => isset($data['unit']) && is_numeric($data['unit']) ? (int) $data['unit'] : null, // integer, nullable
'prev_total_area' => $data['prev_total_area'] ?? 0,
'koefisien_dasar_bangunan' => $data['koefisien_dasar_bangunan'] ?? 0, // Previous information
'koefisien_lantai_bangunan' => $data['koefisien_lantai_bangunan'] ?? 0, 'prev_retribution' => self::cleanNumericValue($data['prev_retribution'] ?? null, true), // decimal(15,2), nullable
'koefisien_lantai_hijau' => $data['koefisien_lantai_hijau'] ?? 0, 'prev_pbg' => $data['prev_pbg'] ?? null, // string, nullable
'koefisien_tapak_basement' => $data['koefisien_tapak_basement'] ?? 0, 'prev_total_area' => self::cleanNumericValue($data['prev_total_area'] ?? null, true), // decimal(10,2), nullable
'ketinggian_bangunan' => $data['ketinggian_bangunan'] ?? 0,
// Coefficients - all nullable, decimal(8,4)
'koefisien_dasar_bangunan' => self::cleanNumericValue($data['koefisien_dasar_bangunan'] ?? null, true),
'koefisien_lantai_bangunan' => self::cleanNumericValue($data['koefisien_lantai_bangunan'] ?? null, true),
'koefisien_lantai_hijau' => self::cleanNumericValue($data['koefisien_lantai_hijau'] ?? null, true),
'koefisien_tapak_basement' => self::cleanNumericValue($data['koefisien_tapak_basement'] ?? null, true),
'ketinggian_bangunan' => self::cleanNumericValue($data['ketinggian_bangunan'] ?? null, true), // decimal(8,2), nullable
// Road information - all nullable
'jalan_arteri' => $data['jalan_arteri'] ?? null, 'jalan_arteri' => $data['jalan_arteri'] ?? null,
'jalan_kolektor' => $data['jalan_kolektor'] ?? null, 'jalan_kolektor' => $data['jalan_kolektor'] ?? null,
'jalan_bangunan' => $data['jalan_bangunan'] ?? null, 'jalan_bangunan' => $data['jalan_bangunan'] ?? null,
'gsb' => $data['gsb'] ?? null, 'gsb' => self::cleanNumericValue($data['gsb'] ?? null, true), // decimal(8,2), nullable
'kkr_number' => $data['kkr_number'] ?? null, 'kkr_number' => $data['kkr_number'] ?? null, // string, nullable
// Unit data as JSON - nullable
'unit_data' => $data['unit_data'] ?? null, 'unit_data' => $data['unit_data'] ?? null,
'is_mbr' => $data['is_mbr'] ?? false,
'code' => $data['code'] ?? null, // Additional flags
'building_ward_id' => $data['building_ward_id'] ?? null, 'is_mbr' => (bool) ($data['is_mbr'] ?? false), // boolean, default false
'building_ward_name' => $data['building_ward_name'] ?? null, 'code' => $data['code'] ?? "N/A", // string, required
'building_district_id' => $data['building_district_id'] ?? null,
'building_district_name' => $data['building_district_name'] ?? null, // Building location information - all required
'building_regency_id' => $data['building_regency_id'] ?? null, 'building_ward_id' => self::cleanIntegerValue($data['building_ward_id'] ?? 0), // bigInteger, required
'building_regency_name' => $data['building_regency_name'] ?? null, 'building_ward_name' => $data['building_ward_name'] ?? "N/A", // string, required
'building_province_id' => $data['building_province_id'] ?? null, 'building_district_id' => self::cleanIntegerValue($data['building_district_id'] ?? 0), // integer, required
'building_province_name' => $data['building_province_name'] ?? null, 'building_district_name' => $data['building_district_name'] ?? "N/A", // string, required
'building_address' => $data['building_address'] ?? null, 'building_regency_id' => self::cleanIntegerValue($data['building_regency_id'] ?? 0), // integer, required
'latitude' => $data['latitude'] ?? null, 'building_regency_name' => $data['building_regency_name'] ?? "N/A", // string, required
'longitude' => $data['longitude'] ?? null, 'building_province_id' => self::cleanIntegerValue($data['building_province_id'] ?? 0), // integer, required
'building_province_name' => $data['building_province_name'] ?? "N/A", // string, required
'building_address' => $data['building_address'] ?? "N/A", // text, required
// Coordinates - decimal(15,8), nullable
'latitude' => self::cleanCoordinate($data['latitude'] ?? null),
'longitude' => self::cleanCoordinate($data['longitude'] ?? null),
// Additional files - nullable
'building_photo' => $data['building_photo'] ?? null, 'building_photo' => $data['building_photo'] ?? null,
'pbg_parent' => $data['pbg_parent'] ?? null, 'pbg_parent' => $data['pbg_parent'] ?? null,
'api_created_at' => isset($data['created_at']) ? Carbon::parse($data['created_at'])->format('Y-m-d H:i:s') : null,
// Original created_at from API - nullable
'api_created_at' => self::parseDateTime($data['created_at'] ?? null),
]; ];
return static::updateOrCreate( return static::updateOrCreate(

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pbg_task', function (Blueprint $table) {
$table->boolean('is_valid')->default(true)->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pbg_task', function (Blueprint $table) {
$table->dropColumn('is_valid');
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('bigdata_resumes', function (Blueprint $table) {
$table->renameColumn('non_business_dlh_count', 'business_dlh_count');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('bigdata_resumes', function (Blueprint $table) {
$table->renameColumn('business_dlh_count', 'non_business_dlh_count');
});
}
};

View File

@@ -3,6 +3,21 @@ import GlobalConfig, { addThousandSeparators } from "../global-config.js";
import InitDatePicker from "../utils/InitDatePicker.js"; import InitDatePicker from "../utils/InitDatePicker.js";
class BigData { class BigData {
// Helper function to safely access nested object properties with default values
safeGet(obj, path, defaultValue = 0) {
try {
return path.split(".").reduce((current, key) => {
return current &&
current[key] !== null &&
current[key] !== undefined
? current[key]
: defaultValue;
}, obj);
} catch (error) {
return defaultValue;
}
}
async init() { async init() {
try { try {
new InitDatePicker( new InitDatePicker(
@@ -25,6 +40,14 @@ class BigData {
try { try {
this.resumeBigData = await this.getBigDataResume(filterDate); this.resumeBigData = await this.getBigDataResume(filterDate);
// Ensure resumeBigData is not null/undefined
if (!this.resumeBigData) {
this.resumeBigData = {};
console.warn(
"No data received, using empty object with default values"
);
}
this.initChartTargetPAD(filterDate); this.initChartTargetPAD(filterDate);
this.initChartUsaha(); this.initChartUsaha();
this.initChartNonUsaha(); this.initChartNonUsaha();
@@ -43,6 +66,8 @@ class BigData {
this.initChartNonBusinessDLH(); this.initChartNonBusinessDLH();
} catch (e) { } catch (e) {
console.error(e); console.error(e);
// Initialize with empty data if there's an error
this.resumeBigData = {};
} }
} }
@@ -92,14 +117,24 @@ class BigData {
document document
.querySelectorAll(".document-total.chart-target-pad") .querySelectorAll(".document-total.chart-target-pad")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"target_pad.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
this.resumeBigData.target_pad.sum.toString() sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-target-pad") .querySelectorAll(".small-percentage.chart-target-pad")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.target_pad.percentage}%`; const percentage = this.safeGet(
this.resumeBigData,
"target_pad.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartTotalPotensi() { initChartTotalPotensi() {
@@ -108,44 +143,68 @@ class BigData {
document document
.querySelectorAll(".document-count.chart-total-potensi") .querySelectorAll(".document-count.chart-total-potensi")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${countAll}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.total_potensi.count}`; this.resumeBigData,
"total_potensi.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-total-potensi") .querySelectorAll(".document-total.chart-total-potensi")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"total_potensi.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.bigTotalPotensi.toString() sum.toString()
this.resumeBigData.total_potensi.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-total-potensi") .querySelectorAll(".small-percentage.chart-total-potensi")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.resultPercentage}%`; const percentage = this.safeGet(
element.innerText = `${this.resumeBigData.total_potensi.percentage}%`; this.resumeBigData,
"total_potensi.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartVerificationDocuments() { initChartVerificationDocuments() {
document document
.querySelectorAll(".document-count.chart-berkas-terverifikasi") .querySelectorAll(".document-count.chart-berkas-terverifikasi")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataVerification.count}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.verified_document.count}`; this.resumeBigData,
"verified_document.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-berkas-terverifikasi") .querySelectorAll(".document-total.chart-berkas-terverifikasi")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"verified_document.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.bigTotalVerification.toString() sum.toString()
this.resumeBigData.verified_document.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-berkas-terverifikasi") .querySelectorAll(".small-percentage.chart-berkas-terverifikasi")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.percetageResultVerification}%`; const percentage = this.safeGet(
element.innerText = `${this.resumeBigData.verified_document.percentage}%`; this.resumeBigData,
"verified_document.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartNonVerificationDocuments() { initChartNonVerificationDocuments() {
@@ -154,17 +213,25 @@ class BigData {
".document-count.chart-berkas-belum-terverifikasi" ".document-count.chart-berkas-belum-terverifikasi"
) )
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataNonVerification.count}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.non_verified_document.count}`; this.resumeBigData,
"non_verified_document.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll( .querySelectorAll(
".document-total.chart-berkas-belum-terverifikasi" ".document-total.chart-berkas-belum-terverifikasi"
) )
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"non_verified_document.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.bigTotalNonVerification.toString() sum.toString()
this.resumeBigData.non_verified_document.sum.toString()
)}`; )}`;
}); });
document document
@@ -172,52 +239,80 @@ class BigData {
".small-percentage.chart-berkas-belum-terverifikasi" ".small-percentage.chart-berkas-belum-terverifikasi"
) )
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.percentageResultNonVerification}%`; const percentage = this.safeGet(
element.innerText = `${this.resumeBigData.non_verified_document.percentage}%`; this.resumeBigData,
"non_verified_document.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartUsaha() { initChartUsaha() {
document document
.querySelectorAll(".document-count.chart-business") .querySelectorAll(".document-count.chart-business")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataBusiness.count}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.business_document.count}`; this.resumeBigData,
"business_document.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-business") .querySelectorAll(".document-total.chart-business")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"business_document.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.bigTotalBusiness.toString() sum.toString()
this.resumeBigData.business_document.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-business") .querySelectorAll(".small-percentage.chart-business")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.percentageResultBusiness}%`; const percentage = this.safeGet(
element.innerText = `${this.resumeBigData.business_document.percentage}%`; this.resumeBigData,
"business_document.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartNonUsaha() { initChartNonUsaha() {
document document
.querySelectorAll(".document-count.chart-non-business") .querySelectorAll(".document-count.chart-non-business")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataNonBusiness.count}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.non_business_document.count}`; this.resumeBigData,
"non_business_document.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-non-business") .querySelectorAll(".document-total.chart-non-business")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"non_business_document.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.bigTotalNonBusiness.toString() sum.toString()
this.resumeBigData.non_business_document.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-non-business") .querySelectorAll(".small-percentage.chart-non-business")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.percentageResultNonBusiness}%`; const percentage = this.safeGet(
element.innerText = `${this.resumeBigData.non_business_document.percentage}%`; this.resumeBigData,
"non_business_document.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartKekuranganPotensi() { initChartKekuranganPotensi() {
@@ -229,129 +324,226 @@ class BigData {
document document
.querySelectorAll(".document-total.chart-kekurangan-potensi") .querySelectorAll(".document-total.chart-kekurangan-potensi")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"kekurangan_potensi.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.totalKekuranganPotensi.toString() sum.toString()
this.resumeBigData.kekurangan_potensi.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-kekurangan-potensi") .querySelectorAll(".small-percentage.chart-kekurangan-potensi")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.percentageKekuranganPotensi}%`; const percentage = this.safeGet(
element.innerText = `${this.resumeBigData.kekurangan_potensi.percentage}%`; this.resumeBigData,
"kekurangan_potensi.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartRealisasiTerbitPBG() { initChartRealisasiTerbitPBG() {
document document
.querySelectorAll(".document-count.chart-realisasi-tebit-pbg") .querySelectorAll(".document-count.chart-realisasi-tebit-pbg")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataCountRealisasiTerbit}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.realisasi_terbit.count}`; this.resumeBigData,
"realisasi_terbit.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-realisasi-tebit-pbg") .querySelectorAll(".document-total.chart-realisasi-tebit-pbg")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"realisasi_terbit.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.dataSumRealisasiTerbit sum.toString()
this.resumeBigData.realisasi_terbit.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg") .querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.realisasi_terbit.percentage}%`; const percentage = this.safeGet(
this.resumeBigData,
"realisasi_terbit.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartMenungguKlikDPMPTSP() { initChartMenungguKlikDPMPTSP() {
document document
.querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp") .querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.count}`; this.resumeBigData,
"menunggu_klik_dpmptsp.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp") .querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"menunggu_klik_dpmptsp.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.dataSumMenungguKlikDPMPTSP sum.toString()
this.resumeBigData.menunggu_klik_dpmptsp.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp") .querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.percentage}%`; const percentage = this.safeGet(
this.resumeBigData,
"menunggu_klik_dpmptsp.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartProsesDinasTeknis() { initChartProsesDinasTeknis() {
document document
.querySelectorAll(".document-count.chart-proses-dinas-teknis") .querySelectorAll(".document-count.chart-proses-dinas-teknis")
.forEach((element) => { .forEach((element) => {
// element.innerText = `${this.dataCountProsesDinasTeknis}`; const count = this.safeGet(
element.innerText = `${this.resumeBigData.proses_dinas_teknis.count}`; this.resumeBigData,
"proses_dinas_teknis.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-proses-dinas-teknis") .querySelectorAll(".document-total.chart-proses-dinas-teknis")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"proses_dinas_teknis.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
// this.dataSumProsesDinasTeknis sum.toString()
this.resumeBigData.proses_dinas_teknis.sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-proses-dinas-teknis") .querySelectorAll(".small-percentage.chart-proses-dinas-teknis")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.proses_dinas_teknis.percentage}%`; const percentage = this.safeGet(
this.resumeBigData,
"proses_dinas_teknis.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartPotensiTataRuang() { initChartPotensiTataRuang() {
document document
.querySelectorAll(".document-count.chart-potensi-tata-ruang") .querySelectorAll(".document-count.chart-potensi-tata-ruang")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.tata_ruang.count}`; const count = this.safeGet(
this.resumeBigData,
"tata_ruang.count",
0
);
element.innerText = `${count}`;
}); });
document document
.querySelectorAll(".document-total.chart-potensi-tata-ruang") .querySelectorAll(".document-total.chart-potensi-tata-ruang")
.forEach((element) => { .forEach((element) => {
const sum = this.safeGet(
this.resumeBigData,
"tata_ruang.sum",
0
);
element.innerText = `Rp.${addThousandSeparators( element.innerText = `Rp.${addThousandSeparators(
this.resumeBigData.tata_ruang.sum.toString() sum.toString()
)}`; )}`;
}); });
document document
.querySelectorAll(".small-percentage.chart-potensi-tata-ruang") .querySelectorAll(".small-percentage.chart-potensi-tata-ruang")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.tata_ruang.percentage}%`; const percentage = this.safeGet(
this.resumeBigData,
"tata_ruang.percentage",
0
);
element.innerText = `${percentage}%`;
}); });
} }
initChartBusinessRAB() { initChartBusinessRAB() {
document.querySelectorAll("#business-rab-count").forEach((element) => { document.querySelectorAll("#business-rab-count").forEach((element) => {
element.innerText = `${this.resumeBigData.business_rab_count}`; const count = this.safeGet(
this.resumeBigData,
"business_rab_count",
0
);
element.innerText = `${count}`;
}); });
} }
initChartBusinessKRK() { initChartBusinessKRK() {
document.querySelectorAll("#business-krk-count").forEach((element) => { document.querySelectorAll("#business-krk-count").forEach((element) => {
element.innerText = `${this.resumeBigData.business_krk_count}`; const count = this.safeGet(
this.resumeBigData,
"business_krk_count",
0
);
element.innerText = `${count}`;
});
}
initChartBusinessDLH() {
document.querySelectorAll("#business-dlh-count").forEach((element) => {
const count = this.safeGet(
this.resumeBigData,
"business_dlh_count",
0
);
element.innerText = `${count}`;
}); });
} }
initChartNonBusinessRAB() { initChartNonBusinessRAB() {
document document
.querySelectorAll("#non-business-rab-count") .querySelectorAll("#non-business-rab-count")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.non_business_rab_count}`; const count = this.safeGet(
this.resumeBigData,
"non_business_rab_count",
0
);
element.innerText = `${count}`;
}); });
} }
initChartNonBusinessKRK() { initChartNonBusinessKRK() {
document document
.querySelectorAll("#non-business-krk-count") .querySelectorAll("#non-business-krk-count")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.non_business_krk_count}`; const count = this.safeGet(
this.resumeBigData,
"non_business_krk_count",
0
);
element.innerText = `${count}`;
}); });
} }
initChartNonBusinessDLH() { initChartNonBusinessDLH() {
document document
.querySelectorAll("#non-business-dlh-count") .querySelectorAll("#non-business-dlh-count")
.forEach((element) => { .forEach((element) => {
element.innerText = `${this.resumeBigData.non_business_dlh_count}`; const count = this.safeGet(
this.resumeBigData,
"non_business_dlh_count",
0
);
element.innerText = `${count}`;
}); });
} }
} }

View File

@@ -10,6 +10,7 @@ class PbgTaskAssignments {
this.initTablePbgTaskAssignments(); this.initTablePbgTaskAssignments();
this.handleUpdateData(); this.handleUpdateData();
this.initDatePicker(); this.initDatePicker();
this.initIsValidToggle();
} }
initDatePicker() { initDatePicker() {
@@ -20,6 +21,30 @@ class PbgTaskAssignments {
}); });
} }
initIsValidToggle() {
const checkbox = document.getElementById("is_valid");
const statusText = document.querySelector(".status-text");
const statusDescription = statusText?.nextElementSibling;
if (checkbox && statusText) {
checkbox.addEventListener("change", function () {
if (this.checked) {
statusText.textContent = "Data Valid";
if (statusDescription) {
statusDescription.textContent =
"Data telah diverifikasi dan sesuai";
}
} else {
statusText.textContent = "Data Tidak Valid";
if (statusDescription) {
statusDescription.textContent =
"Data perlu diverifikasi atau diperbaiki";
}
}
});
}
}
initTablePbgTaskAssignments() { initTablePbgTaskAssignments() {
let tableContainer = document.getElementById( let tableContainer = document.getElementById(
"table-pbg-task-assignments" "table-pbg-task-assignments"
@@ -92,6 +117,12 @@ class PbgTaskAssignments {
formData.forEach((value, key) => { formData.forEach((value, key) => {
formObject[key] = value; formObject[key] = value;
}); });
// Handle checkbox properly - ensure boolean value is sent
const isValidCheckbox = document.getElementById("is_valid");
if (isValidCheckbox) {
formObject["is_valid"] = isValidCheckbox.checked ? 1 : 0;
}
fetch(form.action, { fetch(form.action, {
method: "PUT", // Ensure your Laravel route is set to accept PUT requests method: "PUT", // Ensure your Laravel route is set to accept PUT requests
body: JSON.stringify(formObject), // Convert form data to JSON body: JSON.stringify(formObject), // Convert form data to JSON

View File

@@ -1,6 +1,102 @@
// PBG Task Show Page Styles // PBG Task Show Page Styles
// Custom styles for data lists display (List Layout) // Custom styles for data lists display (List Layout)
// Enhanced checkbox styling for is_valid field
.form-check.form-switch {
padding-left: 0;
.form-check-input {
width: 3.25rem;
height: 1.75rem;
border-radius: 1rem;
background-color: #dc3545;
border: none;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
margin-left: 0;
// Remove default browser styling
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
&:checked {
background-color: #28a745;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
}
&:focus {
box-shadow: 0 0 0 0.2rem rgba(93, 135, 255, 0.25);
outline: none;
}
&:not(:checked) {
background-color: #dc3545;
}
// The toggle circle
&::before {
content: "";
position: absolute;
top: 0.125rem;
left: 0.125rem;
width: 1.5rem;
height: 1.5rem;
background-color: #fff;
border-radius: 50%;
transition: all 0.3s ease;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
z-index: 1;
}
// Animation for checked state
&:checked::before {
transform: translateX(1.5rem);
}
}
.form-check-label {
margin-left: 1rem;
cursor: pointer;
padding-left: 0;
.status-text {
font-weight: 600;
font-size: 1rem;
color: #2c3e50;
transition: color 0.3s ease;
}
small {
font-size: 0.85rem;
margin-top: 0.25rem;
line-height: 1.3;
}
}
}
// Status indicator styling
.status-validation-container {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 1rem;
transition: all 0.3s ease;
&.valid {
background: #d4edda;
border-color: #c3e6cb;
color: #155724;
}
&.invalid {
background: #f8d7da;
border-color: #f5c6cb;
color: #721c24;
}
}
.data-list-section { .data-list-section {
.section-header { .section-header {
border-bottom: 2px solid #f8f9fa; border-bottom: 2px solid #f8f9fa;

View File

@@ -100,15 +100,15 @@
</div> </div>
<div style="position: absolute; top: 50px; left: 900px; width: 200px; height: 200px; "> <div style="position: absolute; top: 50px; left: 900px; width: 200px; height: 200px; ">
<x-custom-circle title="RAB dan Gambar" size="medium" style="background-color: #c23c3c;float:left;margin-left:250px;" <x-custom-circle title="RAB dan Gambar" size="medium" style="background-color: #c248a7;float:left;margin-left:250px;"
visible_data="true" data_id="business-rab-count" data_count="0" visible_data="true" data_id="non-business-rab-count" data_count="0"
document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}" document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}"
/> />
</div> </div>
<div style="position: absolute; top: 160px; left: 900px; width: 200px; height: 200px; "> <div style="position: absolute; top: 160px; left: 900px; width: 200px; height: 200px; ">
<x-custom-circle title="KRK" size="medium" style="background-color: #295040;float:left;margin-left:250px;" <x-custom-circle title="KRK" size="medium" style="background-color: #295040;float:left;margin-left:250px;"
visible_data="true" data_id="business-krk-count" data_count="0" visible_data="true" data_id="non-business-krk-count" data_count="0"
document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}" document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}"
/> />
</div> </div>
@@ -123,22 +123,22 @@
</div> </div>
<div style="position: absolute; top: 350px; left: 900px; width: 200px; height: 200px; "> <div style="position: absolute; top: 350px; left: 900px; width: 200px; height: 200px; ">
<x-custom-circle title="RAB dan Gambar" size="medium" style="background-color: #ad4343;float:left;margin-left:250px;" <x-custom-circle title="RAB dan Gambar" size="medium" style="background-color: #c248a7;float:left;margin-left:250px;"
visible_data="true" data_id="non-business-rab-count" data_count="0" visible_data="true" data_id="business-rab-count" data_count="0"
document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}" document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}"
/> />
</div> </div>
<div style="position: absolute; top: 460px; left: 900px; width: 200px; height: 200px; "> <div style="position: absolute; top: 460px; left: 900px; width: 200px; height: 200px; ">
<x-custom-circle title="KRK" size="medium" style="background-color: #51db51;float:left;margin-left:250px;" <x-custom-circle title="KRK" size="medium" style="background-color: #1d8b1d;float:left;margin-left:250px;"
visible_data="true" data_id="non-business-krk-count" data_count="0" visible_data="true" data_id="business-krk-count" data_count="0"
document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}" document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}"
/> />
</div> </div>
<div style="position: absolute; top: 570px; left: 900px; width: 200px; height: 200px; "> <div style="position: absolute; top: 570px; left: 900px; width: 200px; height: 200px; ">
<x-custom-circle title="DLH" size="medium" style="background-color: #331d04;float:left;margin-left:250px;" <x-custom-circle title="DLH" size="medium" style="background-color: #351d02;float:left;margin-left:250px;"
visible_data="true" data_id="non-business-dlh-count" data_count="0" visible_data="true" data_id="business-dlh-count" data_count="0"
document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}" document_url="{{ route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) }}"
/> />
</div> </div>

View File

@@ -15,7 +15,7 @@ class="authentication-bg"
<div class="row align-items-center g-0"> <div class="row align-items-center g-0">
<div class="col"> <div class="col">
<div class="mx-auto mb-4 text-center"> <div class="mx-auto mb-4 text-center">
<img src="/images/simbg-dputr.png" alt="auth" height="250" class="mt-5 mb-3" /> <img src="{{ asset('images/simbg-dputr.png') }}" alt="auth" height="250" class="mt-5 mb-3" />
<h2 class="fs-22 lh-base">Service Unavailable!</h2> <h2 class="fs-22 lh-base">Service Unavailable!</h2>
<p class="text-muted mt-1 mb-4">Our site is currently undergoing scheduled maintenance.<br /> Please check back later.</p> <p class="text-muted mt-1 mb-4">Our site is currently undergoing scheduled maintenance.<br /> Please check back later.</p>

View File

@@ -4,22 +4,45 @@
@include('layouts.partials/page-title', ['title' => 'Home', 'subtitle' => 'Home']) @include('layouts.partials/page-title', ['title' => 'Home', 'subtitle' => 'Home'])
<div className="container d-flex justify-content-center align-items-center min-vh-100 bg-light"> <div class="container-fluid bg-gradient-primary">
<div className="col-lg-8 col-md-10 col-sm-12"> <div class="container">
<div className="card shadow-lg rounded-3 p-4"> <div class="row justify-content-center">
<div className="card-body text-center"> <div class="col-lg-10 col-xl-8">
<h1 className="card-title text-primary">Selamat Datang di SIBEDAS PBG!</h1> <div class="card border-0 shadow-lg">
<p className="card-text text-secondary mt-3"> <div class="card-body">
Sistem Informasi Berbasis Data (SIBEDAS) adalah sebuah sistem yang dirancang untuk mengelola dan mengolah data pegawai secara efektif dan efisien. <div class="text-center mb-4">
Dengan teknologi modern, SIBEDAS memungkinkan pegawai untuk mendata, melihat, dan memanipulasi informasi pegawai dengan mudah. <h1 class="display-4 fw-bold text-secondary mb-3">
<i class="fas fa-building me-3"></i>SIBEDAS PBG
</h1>
<div class="bg-secondary" style="height: 3px; width: 80px; margin: 0 auto;"></div>
</div>
<div class="row">
<div class="col-12">
<div class="bg-light rounded-3 p-4 mb-4">
<h5 class="text-secondary fw-semibold mb-3">
<i class="fas fa-info-circle text-primary me-2"></i>Tentang Aplikasi
</h5>
<p class="text-secondary mb-0 lh-lg">
Aplikasi SIBEDAS PBG merupakan sistem pendukung yang dirancang untuk membantu pimpinan dalam melakukan pengawasan dan monitoring terhadap berkas pengajuan Persetujuan Bangunan Gedung (PBG) yang tercatat di SIMBG.
</p> </p>
<p className="card-text text-secondary"> </div>
PBG (Pegawai Badan Kepegawaian) merupakan unit kerja yang bertanggung jawab atas administrasi kepegawaian.
Melalui SIBEDAS PBG, proses manajemen data pegawai menjadi lebih terstruktur, transparan, dan mudah diakses kapan saja. <div class="bg-light rounded-3 p-4">
<h5 class="text-secondary fw-semibold mb-3">
<i class="fas fa-chart-line text-success me-2"></i>Manfaat & Keunggulan
</h5>
<p class="text-secondary mb-0 lh-lg">
Melalui SIBEDAS PBG, pimpinan dapat memantau secara langsung status perkembangan setiap berkas, mengidentifikasi pengajuan yang belum selesai, dan memastikan tindak lanjut penyelesaian dilakukan tepat waktu. Pengawasan yang lebih terstruktur, cepat, dan akurat ini tidak hanya meningkatkan kualitas pelayanan kepada masyarakat, tetapi juga mendukung tercapainya target Pendapatan Asli Daerah (PAD) melalui optimalisasi penyelesaian berkas PBG.
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</div>
</div>
</div>
@endsection @endsection

View File

@@ -26,7 +26,7 @@ class="authentication-bg"
</a> --> </a> -->
</div> </div>
<img src="/images/simbg-dputr.png" alt="auth" height="250" class="mt-5 mb-3" /> <img src="{{ asset('images/simbg-dputr.png') }}" alt="dputr logo" height="250" class="mt-5 mb-3" />
<h2 class="fs-22 lh-base">Page Not Found !</h2> <h2 class="fs-22 lh-base">Page Not Found !</h2>
<p class="text-muted mt-1 mb-4">The page you're trying to reach seems to have gone <br /> missing in the digital wilderness.</p> <p class="text-muted mt-1 mb-4">The page you're trying to reach seems to have gone <br /> missing in the digital wilderness.</p>

View File

@@ -80,10 +80,24 @@
<label for="due_date" class="form-label">Due Date</label> <label for="due_date" class="form-label">Due Date</label>
<input type="text" class="form-control" id="datepicker_due_date" name="due_date" value="{{$data->due_date}}"> <input type="text" class="form-control" id="datepicker_due_date" name="due_date" value="{{$data->due_date}}">
</div> </div>
<div> <div class="mb-3">
<label for="task_created_at" class="form-label">Task Created At</label> <label for="task_created_at" class="form-label">Task Created At</label>
<input type="datetime-local" class="form-control" id="task_created_at" name="task_created_at" value="{{$data->task_created_at}}" disabled> <input type="datetime-local" class="form-control" id="task_created_at" name="task_created_at" value="{{$data->task_created_at}}" disabled>
</div> </div>
<div class="mb-3">
<label class="form-label">Status Validasi Data</label>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="is_valid" name="is_valid" value="1" {{ $data->is_valid ? 'checked' : '' }}>
<label class="form-check-label" for="is_valid">
<span class="status-text">{{ $data->is_valid ? 'Data Valid' : 'Data Tidak Valid' }}</span>
<small class="text-muted d-block">
{{ $data->is_valid ? 'Data telah diverifikasi dan sesuai' : 'Data perlu diverifikasi atau diperbaiki' }}
</small>
</label>
</div>
<!-- Hidden input to ensure false value is sent when unchecked -->
<input type="hidden" name="is_valid" value="0">
</div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">