count spatial plannings business and non business and create pbg task detail and add to syncrone daily

This commit is contained in:
arifal
2025-06-18 13:45:35 +07:00
parent f2eb998ac5
commit e71dd7d213
11 changed files with 509 additions and 202 deletions

View File

@@ -1,101 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use App\Models\SpatialPlanning;
use App\Models\RetributionProposal;
class CheckSpatialPlanningConstraints extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'spatial:check-constraints';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check spatial planning foreign key constraints and show statistics';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Checking Spatial Planning Constraints...');
$this->newLine();
try {
// Get total spatial plannings
$totalSpatialPlannings = SpatialPlanning::count();
// Get spatial plannings with retribution proposals
$withProposals = SpatialPlanning::whereHas('retributionProposals')->count();
// Get spatial plannings without retribution proposals
$withoutProposals = SpatialPlanning::whereDoesntHave('retributionProposals')->count();
// Get total retribution proposals
$totalProposals = RetributionProposal::count();
// Get retribution proposals linked to spatial plannings
$linkedProposals = RetributionProposal::whereNotNull('spatial_planning_id')->count();
// Get standalone retribution proposals
$standaloneProposals = RetributionProposal::whereNull('spatial_planning_id')->count();
// Display statistics
$this->table(
['Metric', 'Count'],
[
['Total Spatial Plannings', $totalSpatialPlannings],
['├─ With Retribution Proposals', $withProposals],
['└─ Without Retribution Proposals', $withoutProposals],
['', ''],
['Total Retribution Proposals', $totalProposals],
['├─ Linked to Spatial Planning', $linkedProposals],
['└─ Standalone Proposals', $standaloneProposals],
]
);
$this->newLine();
// Show constraint implications
if ($withProposals > 0) {
$this->warn("⚠️ CONSTRAINT WARNING:");
$this->warn(" {$withProposals} spatial plannings have retribution proposals linked to them.");
$this->warn(" These cannot be deleted directly due to foreign key constraints.");
$this->newLine();
$this->info("💡 TRUNCATE OPTIONS:");
$this->info(" • Use --truncate to delete ALL data (spatial plannings + linked proposals)");
$this->info(" • Use --safe-truncate to delete only spatial plannings without proposals");
$this->info(" • Manual cleanup: Delete proposals first, then spatial plannings");
} else {
$this->info("✅ No foreign key constraints found.");
$this->info(" All spatial plannings can be safely truncated.");
}
$this->newLine();
// Show example commands
$this->info("📋 EXAMPLE COMMANDS:");
$this->info(" php artisan spatial:init --truncate # Delete all data (smart method)");
$this->info(" php artisan spatial:init --safe-truncate # Delete safe data only");
$this->info(" php artisan spatial:init --force-truncate # Force truncate (disable FK checks)");
$this->info(" php artisan spatial:init file.csv --truncate # Import with truncate");
return 0;
} catch (\Exception $e) {
$this->error('Error checking constraints: ' . $e->getMessage());
return 1;
}
}
}

View File

@@ -1,45 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class ClearDatabaseSessions extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'session:clear-db {--force : Force the operation without confirmation}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Clear all database sessions';
/**
* Execute the console command.
*/
public function handle()
{
if (!$this->option('force') && !$this->confirm('Are you sure you want to clear all database sessions?')) {
$this->info('Operation cancelled.');
return 0;
}
try {
$count = DB::table('sessions')->count();
DB::table('sessions')->delete();
$this->info("Successfully cleared {$count} database sessions.");
return 0;
} catch (\Exception $e) {
$this->error('Failed to clear database sessions: ' . $e->getMessage());
return 1;
}
}
}

View File

@@ -42,54 +42,4 @@ class ScrapingData extends Command
$this->info("Scraping job dispatched successfully");
}
/**
* Execute the console command.
*/
// public function handle()
// {
// try {
// // Create a record with "processing" status
// $import_datasource = ImportDatasource::create([
// 'message' => 'Initiating scraping...',
// 'response_body' => null,
// 'status' => 'processing',
// 'start_time' => now()
// ]);
// // Run the service
// $service_google_sheet = new ServiceGoogleSheet();
// $service_google_sheet->run_service();
// // Run the ServicePbgTask with injected Guzzle Client
// $this->service_pbg_task->run_service();
// // run the service pbg task assignments
// $this->service_tab_pbg_task->run_service();
// // Update the record status to "success" after completion
// $import_datasource->update([
// 'status' => 'success',
// 'message' => 'Scraping completed successfully.',
// 'finish_time' => now()
// ]);
// } catch (\Exception $e) {
// // Log the error for debugging
// Log::error('Scraping failed: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
// // Handle errors by updating the status to "failed"
// if (isset($import_datasource)) {
// $import_datasource->update([
// 'status' => 'failed',
// 'response_body' => 'Error: ' . $e->getMessage(),
// 'finish_time' => now()
// ]);
// }
// }
// }
}

View File

@@ -17,12 +17,16 @@ class LackOfPotentialController extends Controller
$total_reklame = Advertisement::count();
$total_pdam = Customer::count();
$total_tata_ruang = SpatialPlanning::count();
$total_tata_ruang_usaha = SpatialPlanning::where('building_function','like', '%usaha%')->count();
$total_tata_ruang_non_usaha = SpatialPlanning::where('building_function','like', '%hunian%')->count();
$data_report_tourism = TourismBasedKBLI::all();
return response()->json([
'total_reklame' => $total_reklame,
'total_pdam' => $total_pdam,
'total_tata_ruang' => $total_tata_ruang,
'total_tata_ruang_usaha' => $total_tata_ruang_usaha,
'total_tata_ruang_non_usaha' => $total_tata_ruang_non_usaha,
'data_report' => $data_report_tourism,
], 200);
}catch(\Exception $e){

View File

@@ -60,10 +60,10 @@ class ScrapingDataJob implements ShouldQueue
throw $e;
}
$data_setting_result = $service_google_sheet->get_big_resume_data();
// $data_setting_result = $service_google_sheet->get_big_resume_data();
BigdataResume::generateResumeData($import_datasource->id, "all", $data_setting_result);
BigdataResume::generateResumeData($import_datasource->id, now()->year, $data_setting_result);
// BigdataResume::generateResumeData($import_datasource->id, "all", $data_setting_result);
// BigdataResume::generateResumeData($import_datasource->id, now()->year, $data_setting_result);
// Update status to success
$import_datasource->update([

View File

@@ -38,6 +38,10 @@ class PbgTask extends Model
return $this->hasOne(PbgTaskIndexIntegrations::class, 'pbg_task_uid', 'uuid');
}
public function pbg_task_detail(){
return $this->hasOne(PbgTaskDetail::class, 'pbg_task_uid', 'uuid');
}
public function googleSheet(){
return $this->hasOne(PbgTaskGoogleSheet::class, 'no_registrasi', 'registration_number');
}

View File

@@ -0,0 +1,252 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Carbon\Carbon;
class PbgTaskDetail extends Model
{
protected $table = 'pbg_task_details';
protected $fillable = [
'pbg_task_uid',
'uid',
'nik',
'type_card',
'ownership',
'owner_name',
'ward_id',
'ward_name',
'district_id',
'district_name',
'regency_id',
'regency_name',
'province_id',
'province_name',
'address',
'owner_email',
'owner_phone',
'user',
'name',
'email',
'phone',
'user_nik',
'user_province_id',
'user_province_name',
'user_regency_id',
'user_regency_name',
'user_district_id',
'user_district_name',
'user_address',
'status',
'status_name',
'slf_status',
'slf_status_name',
'sppst_status',
'sppst_file',
'sppst_status_name',
'file_pbg',
'file_pbg_date',
'due_date',
'start_date',
'document_number',
'registration_number',
'function_type',
'application_type',
'application_type_name',
'consultation_type',
'condition',
'prototype',
'permanency',
'building_type',
'building_type_name',
'building_purpose',
'building_use',
'occupancy',
'name_building',
'total_area',
'area',
'area_type',
'height',
'floor',
'floor_area',
'basement',
'basement_height',
'basement_area',
'unit',
'prev_retribution',
'prev_pbg',
'prev_total_area',
'koefisien_dasar_bangunan',
'koefisien_lantai_bangunan',
'koefisien_lantai_hijau',
'koefisien_tapak_basement',
'ketinggian_bangunan',
'jalan_arteri',
'jalan_kolektor',
'jalan_bangunan',
'gsb',
'kkr_number',
'unit_data',
'is_mbr',
'code',
'building_ward_id',
'building_ward_name',
'building_district_id',
'building_district_name',
'building_regency_id',
'building_regency_name',
'building_province_id',
'building_province_name',
'building_address',
'latitude',
'longitude',
'building_photo',
'pbg_parent',
'api_created_at',
];
protected $casts = [
'unit_data' => 'array',
'is_mbr' => 'boolean',
'total_area' => 'decimal:2',
'area' => 'decimal:2',
'height' => 'decimal:2',
'floor_area' => 'decimal:2',
'basement_height' => 'decimal:2',
'basement_area' => 'decimal:2',
'prev_retribution' => 'decimal:2',
'prev_total_area' => 'decimal:2',
'koefisien_dasar_bangunan' => 'decimal:4',
'koefisien_lantai_bangunan' => 'decimal:4',
'koefisien_lantai_hijau' => 'decimal:4',
'koefisien_tapak_basement' => 'decimal:4',
'ketinggian_bangunan' => 'decimal:2',
'gsb' => 'decimal:2',
'latitude' => 'decimal:8',
'longitude' => 'decimal:8',
'file_pbg_date' => 'date',
'due_date' => 'date',
'start_date' => 'date',
'api_created_at' => 'datetime',
];
/**
* Get the PBG task that owns this detail
*/
public function pbgTask(): BelongsTo
{
return $this->belongsTo(PbgTask::class, 'pbg_task_uid', 'uuid');
}
/**
* Create or update PbgTaskDetail from API response
*/
public static function createFromApiResponse(array $data, string $pbgTaskUuid): self
{
$detailData = [
'pbg_task_uid' => $pbgTaskUuid,
'uid' => $data['uid'] ?? null,
'nik' => $data['nik'] ?? null,
'type_card' => $data['type_card'] ?? null,
'ownership' => $data['ownership'] ?? null,
'owner_name' => $data['owner_name'] ?? null,
'ward_id' => $data['ward_id'] ?? null,
'ward_name' => $data['ward_name'] ?? null,
'district_id' => $data['district_id'] ?? null,
'district_name' => $data['district_name'] ?? null,
'regency_id' => $data['regency_id'] ?? null,
'regency_name' => $data['regency_name'] ?? null,
'province_id' => $data['province_id'] ?? null,
'province_name' => $data['province_name'] ?? null,
'address' => $data['address'] ?? null,
'owner_email' => $data['owner_email'] ?? null,
'owner_phone' => $data['owner_phone'] ?? null,
'user' => $data['user'] ?? null,
'name' => $data['name'] ?? null,
'email' => $data['email'] ?? null,
'phone' => $data['phone'] ?? null,
'user_nik' => $data['user_nik'] ?? null,
'user_province_id' => $data['user_province_id'] ?? null,
'user_province_name' => $data['user_province_name'] ?? null,
'user_regency_id' => $data['user_regency_id'] ?? null,
'user_regency_name' => $data['user_regency_name'] ?? null,
'user_district_id' => $data['user_district_id'] ?? null,
'user_district_name' => $data['user_district_name'] ?? null,
'user_address' => $data['user_address'] ?? null,
'status' => $data['status'] ?? null,
'status_name' => $data['status_name'] ?? null,
'slf_status' => $data['slf_status'] ?? null,
'slf_status_name' => $data['slf_status_name'] ?? null,
'sppst_status' => $data['sppst_status'] ?? null,
'sppst_file' => $data['sppst_file'] ?? null,
'sppst_status_name' => $data['sppst_status_name'] ?? null,
'file_pbg' => $data['file_pbg'] ?? null,
'file_pbg_date' => isset($data['file_pbg_date']) ? Carbon::parse($data['file_pbg_date'])->format('Y-m-d') : null,
'due_date' => isset($data['due_date']) ? Carbon::parse($data['due_date'])->format('Y-m-d') : null,
'start_date' => isset($data['start_date']) ? Carbon::parse($data['start_date'])->format('Y-m-d') : null,
'document_number' => $data['document_number'] ?? null,
'registration_number' => $data['registration_number'] ?? null,
'function_type' => $data['function_type'] ?? null,
'application_type' => $data['application_type'] ?? null,
'application_type_name' => $data['application_type_name'] ?? null,
'consultation_type' => $data['consultation_type'] ?? null,
'condition' => $data['condition'] ?? null,
'prototype' => $data['prototype'] ?? null,
'permanency' => $data['permanency'] ?? null,
'building_type' => $data['building_type'] ?? null,
'building_type_name' => $data['building_type_name'] ?? null,
'building_purpose' => $data['building_purpose'] ?? null,
'building_use' => $data['building_use'] ?? null,
'occupancy' => $data['occupancy'] ?? null,
'name_building' => $data['name_building'] ?? null,
'total_area' => $data['total_area'] ?? null,
'area' => $data['area'] ?? null,
'area_type' => $data['area_type'] ?? null,
'height' => $data['height'] ?? null,
'floor' => $data['floor'] ?? null,
'floor_area' => $data['floor_area'] ?? null,
'basement' => $data['basement'] ?? null,
'basement_height' => $data['basement_height'] ?? null,
'basement_area' => $data['basement_area'] ?? null,
'unit' => $data['unit'] ?? null,
'prev_retribution' => $data['prev_retribution'] ?? null,
'prev_pbg' => $data['prev_pbg'] ?? null,
'prev_total_area' => $data['prev_total_area'] ?? null,
'koefisien_dasar_bangunan' => $data['koefisien_dasar_bangunan'] ?? null,
'koefisien_lantai_bangunan' => $data['koefisien_lantai_bangunan'] ?? null,
'koefisien_lantai_hijau' => $data['koefisien_lantai_hijau'] ?? null,
'koefisien_tapak_basement' => $data['koefisien_tapak_basement'] ?? null,
'ketinggian_bangunan' => $data['ketinggian_bangunan'] ?? null,
'jalan_arteri' => $data['jalan_arteri'] ?? null,
'jalan_kolektor' => $data['jalan_kolektor'] ?? null,
'jalan_bangunan' => $data['jalan_bangunan'] ?? null,
'gsb' => $data['gsb'] ?? null,
'kkr_number' => $data['kkr_number'] ?? null,
'unit_data' => $data['unit_data'] ?? null,
'is_mbr' => $data['is_mbr'] ?? false,
'code' => $data['code'] ?? null,
'building_ward_id' => $data['building_ward_id'] ?? null,
'building_ward_name' => $data['building_ward_name'] ?? null,
'building_district_id' => $data['building_district_id'] ?? null,
'building_district_name' => $data['building_district_name'] ?? null,
'building_regency_id' => $data['building_regency_id'] ?? null,
'building_regency_name' => $data['building_regency_name'] ?? null,
'building_province_id' => $data['building_province_id'] ?? null,
'building_province_name' => $data['building_province_name'] ?? null,
'building_address' => $data['building_address'] ?? null,
'latitude' => $data['latitude'] ?? null,
'longitude' => $data['longitude'] ?? null,
'building_photo' => $data['building_photo'] ?? 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,
];
return static::updateOrCreate(
['uid' => $data['uid']],
$detailData
);
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Services;
use App\Models\GlobalSetting;
use App\Models\PbgTask;
use App\Models\PbgTaskDetail;
use App\Models\PbgTaskIndexIntegrations;
use App\Models\PbgTaskPrasarana;
use App\Models\PbgTaskRetributions;
@@ -53,6 +54,7 @@ class ServiceTabPbgTask
}
try{
$this->current_uuid = $pbg_task->uuid;
$this->scraping_task_details($pbg_task->uuid);
$this->scraping_task_assignments($pbg_task->uuid);
$this->scraping_task_retributions($pbg_task->uuid);
$this->scraping_task_integrations($pbg_task->uuid);
@@ -71,6 +73,75 @@ class ServiceTabPbgTask
return $this->current_uuid;
}
private function scraping_task_details($uuid)
{
$url = "{$this->simbg_host}/api/pbg/v1/detail/{$uuid}/";
$options = [
'headers' => [
'Authorization' => "Bearer {$this->user_token}",
'Content-Type' => 'application/json'
]
];
$maxRetries = 3;
$initialDelay = 1;
$retriedAfter401 = false;
for ($retryCount = 0; $retryCount < $maxRetries; $retryCount++) {
try {
$response = $this->client->get($url, $options);
$responseData = json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
if (empty($responseData['data']) || !is_array($responseData['data'])) {
return true;
}
$data = $responseData['data'];
// Use the static method from PbgTaskDetail model to create/update
PbgTaskDetail::createFromApiResponse($data, $uuid);
return $responseData;
} catch (\GuzzleHttp\Exception\ClientException $e) {
if ($e->getCode() === 401 && !$retriedAfter401) {
Log::warning("401 Unauthorized - Refreshing token and retrying...");
try{
$this->refreshToken();
$options['headers']['Authorization'] = "Bearer {$this->user_token}";
$retriedAfter401 = true;
continue;
}catch(\Exception $refreshError){
Log::error("Token refresh and login failed: " . $refreshError->getMessage());
return false;
}
}
return false;
} catch (\GuzzleHttp\Exception\ServerException | \GuzzleHttp\Exception\ConnectException $e) {
if ($e->getCode() === 502) {
Log::warning("502 Bad Gateway - Retrying in {$initialDelay} seconds...");
} else {
Log::error("Network error ({$e->getCode()}) - Retrying in {$initialDelay} seconds...");
}
sleep($initialDelay);
$initialDelay *= 2;
} catch (\GuzzleHttp\Exception\RequestException $e) {
Log::error("Request error ({$e->getCode()}): " . $e->getMessage());
return false;
} catch (\JsonException $e) {
Log::error("JSON decoding error: " . $e->getMessage());
return false;
} catch (\Throwable $e) {
Log::critical("Unhandled error: " . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
return false;
}
}
Log::error("Failed to fetch task details for UUID {$uuid} after {$maxRetries} retries.");
throw new \Exception("Failed to fetch task details for UUID {$uuid} after retries.");
}
private function scraping_task_assignments($uuid)
{
$url = "{$this->simbg_host}/api/pbg/v1/list-tim-penilai/{$uuid}/?page=1&size=10";