calculatorService = $calculatorService; } /** * Execute the console command. */ public function handle() { $this->info('๐Ÿข SISTEM TEST PERHITUNGAN RETRIBUSI PBG'); $this->info('=' . str_repeat('=', 50)); // Test all building types if --all flag is used if ($this->option('all')) { return $this->testAllBuildingTypes(); } // Get input parameters $area = $this->getArea(); $floor = $this->getFloor(); $buildingTypeId = $this->getBuildingType(); if (!$area || !$floor || !$buildingTypeId) { $this->error('โŒ Parameter tidak lengkap!'); return 1; } // Perform calculation $this->performCalculation($buildingTypeId, $floor, $area); return 0; } protected function getArea() { $area = $this->option('area'); if (!$area) { $area = $this->ask('๐Ÿ“ Masukkan luas bangunan (mยฒ)'); } if (!is_numeric($area) || $area <= 0) { $this->error('โŒ Luas bangunan harus berupa angka positif!'); return null; } return (float) $area; } protected function getFloor() { $floor = $this->option('floor'); if (!$floor) { $floor = $this->ask('๐Ÿ—๏ธ Masukkan jumlah lantai (1-6)'); } if (!is_numeric($floor) || $floor < 1 || $floor > 6) { $this->error('โŒ Jumlah lantai harus antara 1-6!'); return null; } return (int) $floor; } protected function getBuildingType() { $type = $this->option('type'); if (!$type) { $this->showBuildingTypes(); $type = $this->ask('๐Ÿข Masukkan ID atau kode building type'); } // Try to find by ID first, then by code $buildingType = null; if (is_numeric($type)) { $buildingType = BuildingType::find($type); } else { $buildingType = BuildingType::where('code', strtoupper($type))->first(); } if (!$buildingType) { $this->error('โŒ Building type tidak ditemukan!'); return null; } return $buildingType->id; } protected function showBuildingTypes() { $this->info('๐Ÿ“‹ DAFTAR BUILDING TYPES:'); $this->line(''); $buildingTypes = BuildingType::with('indices') ->whereHas('indices') // Only types that have indices ->get(); $headers = ['ID', 'Kode', 'Nama', 'Coefficient', 'Free']; $rows = []; foreach ($buildingTypes as $type) { $rows[] = [ $type->id, $type->code, $type->name, $type->indices ? number_format($type->indices->coefficient, 4) : 'N/A', $type->is_free ? 'โœ…' : 'โŒ' ]; } $this->table($headers, $rows); $this->line(''); } protected function performCalculation($buildingTypeId, $floor, $area) { try { // Round area to 2 decimal places to match database storage format $roundedArea = round($area, 2); $result = $this->calculatorService->calculate($buildingTypeId, $floor, $roundedArea, false); $this->displayResults($result, $roundedArea, $floor); } catch (\Exception $e) { $this->error('โŒ Error: ' . $e->getMessage()); return 1; } } protected function displayResults($result, $area, $floor) { $this->info(''); $this->info('๐Ÿ“Š HASIL PERHITUNGAN RETRIBUSI'); $this->info('=' . str_repeat('=', 40)); // Building info $this->line('๐Ÿข Building Type: ' . $result['building_type']['name']); $this->line('๐Ÿ“ Luas Bangunan: ' . number_format($area, 0) . ' mยฒ'); $this->line('๐Ÿ—๏ธ Jumlah Lantai: ' . $floor); if (isset($result['building_type']['is_free']) && $result['building_type']['is_free']) { $this->line(''); $this->info('๐ŸŽ‰ GRATIS - Building type ini tidak dikenakan retribusi'); $this->line('๐Ÿ’ฐ Total Retribusi: Rp 0'); return; } $this->line(''); // Parameters $this->info('๐Ÿ“‹ PARAMETER PERHITUNGAN:'); $indices = $result['indices']; $this->line('โ€ข Coefficient: ' . number_format($indices['coefficient'], 4)); $this->line('โ€ข IP Permanent: ' . number_format($indices['ip_permanent'], 4)); $this->line('โ€ข IP Complexity: ' . number_format($indices['ip_complexity'], 4)); $this->line('โ€ข Locality Index: ' . number_format($indices['locality_index'], 4)); $this->line('โ€ข Height Index: ' . number_format($result['input_parameters']['height_index'], 4)); $this->line(''); // Calculation steps $this->info('๐Ÿ”ข LANGKAH PERHITUNGAN:'); $detail = $result['calculation_detail']; $this->line('1. H5 Raw: ' . number_format($detail['h5_raw'], 6)); $this->line('2. H5 Rounded: ' . number_format($detail['h5'], 4)); $this->line('3. Main Calculation: Rp ' . number_format($detail['main'], 2)); $this->line('4. Infrastructure (50%): Rp ' . number_format($detail['infrastructure'], 2)); $this->line(''); // Final result $this->info('๐Ÿ’ฐ TOTAL RETRIBUSI: ' . $result['formatted_amount'] . ''); $this->line('๐Ÿ“ˆ Per mยฒ: Rp ' . number_format($result['total_retribution'] / $area, 2) . ''); } protected function testAllBuildingTypes() { $area = round($this->option('area') ?: 100, 2); $floor = $this->option('floor') ?: 2; $this->info("๐Ÿงช TESTING SEMUA BUILDING TYPES"); $this->info("๐Ÿ“ Luas: {$area} mยฒ | ๐Ÿ—๏ธ Lantai: {$floor}"); $this->info('=' . str_repeat('=', 60)); $buildingTypes = BuildingType::with('indices') ->whereHas('indices') // Only types that have indices ->orderBy('level') ->orderBy('name') ->get(); $headers = ['Kode', 'Nama', 'Coefficient', 'Total Retribusi', 'Per mยฒ']; $rows = []; foreach ($buildingTypes as $type) { try { $result = $this->calculatorService->calculate($type->id, $floor, $area, false); if ($type->is_free) { $rows[] = [ $type->code, $type->name, 'FREE', 'Rp 0', 'Rp 0' ]; } else { $rows[] = [ $type->code, $type->name, number_format($result['indices']['coefficient'], 4), 'Rp ' . number_format($result['total_retribution'], 0), 'Rp ' . number_format($result['total_retribution'] / $area, 0) ]; } } catch (\Exception $e) { $rows[] = [ $type->code, $type->name, 'ERROR', $e->getMessage(), '-' ]; } } $this->table($headers, $rows); return 0; } }