Compare commits
1 Commits
fc4b419878
...
feat/recre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59cc102c5a |
@@ -2,208 +2,124 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\BuildingFunction;
|
||||
use App\Models\FloorHeightIndex;
|
||||
use App\Models\RetributionProposal;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Services\DynamicRetributionCalculationService;
|
||||
|
||||
class TestExcelFormulaCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'test:excel-formula {--building-function=10} {--floor-area=100} {--floor-number=2}';
|
||||
protected $signature = 'test:excel-formula';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Test Excel formula calculation with sample data';
|
||||
protected $description = 'Test Excel formula implementation for PBG retribution calculation';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('🧮 Testing Excel Formula Calculation');
|
||||
$service = new DynamicRetributionCalculationService();
|
||||
|
||||
$this->info('=== TESTING RUNDOWN 4 IMPLEMENTATION ===');
|
||||
$this->info('Formula: =ROUNDDOWN(($E13*($F13+$G13+(0.5*I$3))),4)');
|
||||
$this->newLine();
|
||||
|
||||
// Get parameters
|
||||
$buildingFunctionId = $this->option('building-function');
|
||||
$floorArea = (float) $this->option('floor-area');
|
||||
$floorNumber = (int) $this->option('floor-number');
|
||||
// Test 1: Hunian Sederhana
|
||||
$this->info('1. HUNIAN SEDERHANA (1 Lantai, 100 m²)');
|
||||
|
||||
// Get building function and parameters
|
||||
$buildingFunction = BuildingFunction::with('parameter')->find($buildingFunctionId);
|
||||
if (!$buildingFunction || !$buildingFunction->parameter) {
|
||||
$this->error("Building function with ID {$buildingFunctionId} not found or has no parameters.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get IP ketinggian for floor
|
||||
$floorHeightIndex = FloorHeightIndex::where('floor_number', $floorNumber)->first();
|
||||
$ipKetinggian = $floorHeightIndex ? $floorHeightIndex->ip_ketinggian : 1.0;
|
||||
|
||||
// Get parameters
|
||||
$parameters = $buildingFunction->parameter->getParametersArray();
|
||||
|
||||
$this->info("Test Parameters:");
|
||||
$this->table(
|
||||
['Parameter', 'Excel Cell', 'Value'],
|
||||
[
|
||||
['Building Function', 'Building Function', $buildingFunction->name],
|
||||
['Floor Area (D13)', 'D13', $floorArea . ' m²'],
|
||||
['Fungsi Bangunan (E13)', 'E13', $parameters['fungsi_bangunan']],
|
||||
['IP Permanen (F13)', 'F13', $parameters['ip_permanen']],
|
||||
['IP Kompleksitas (G13)', 'G13', $parameters['ip_kompleksitas']],
|
||||
['IP Ketinggian (H$3)', 'H$3', $ipKetinggian],
|
||||
['Indeks Lokalitas (N13)', 'N13', $parameters['indeks_lokalitas']],
|
||||
['Base Value', '70350', '70,350'],
|
||||
['Additional Factor ($O$3)', '$O$3', '0.5 (50%)']
|
||||
]
|
||||
$result1 = $service->calculateRetribution(
|
||||
buildingFunctionId: 10, // HUNIAN_SEDERHANA
|
||||
floorLevel: 1,
|
||||
luasBangunan: 100,
|
||||
indeksLokasi: 'sedang',
|
||||
includeInfrastructure: true
|
||||
);
|
||||
|
||||
$this->newLine();
|
||||
if ($result1['success']) {
|
||||
$rundown4 = $result1['calculation_breakdown']['rundown_4_calculation'];
|
||||
$retribution = $result1['calculation_breakdown']['retribution_calculation'];
|
||||
|
||||
// Calculate manually using the Excel formula
|
||||
$fungsi_bangunan = $parameters['fungsi_bangunan'];
|
||||
$ip_permanen = $parameters['ip_permanen'];
|
||||
$ip_kompleksitas = $parameters['ip_kompleksitas'];
|
||||
$indeks_lokalitas = $parameters['indeks_lokalitas'];
|
||||
$base_value = 70350;
|
||||
$additional_factor = 0.5;
|
||||
|
||||
// Step 1: Calculate H13 (floor coefficient)
|
||||
$h13 = $fungsi_bangunan * ($ip_permanen + $ip_kompleksitas + (0.5 * $ipKetinggian));
|
||||
|
||||
// Step 2: Main calculation
|
||||
$main_calculation = 1 * $floorArea * ($indeks_lokalitas * $base_value * $h13 * 1);
|
||||
|
||||
// Step 3: Additional (50%)
|
||||
$additional_calculation = $additional_factor * $main_calculation;
|
||||
|
||||
// Step 4: Total
|
||||
$total_retribution = $main_calculation + $additional_calculation;
|
||||
|
||||
// Create breakdown array
|
||||
$breakdown = [
|
||||
'calculation_steps' => [
|
||||
'step_1_h13' => [
|
||||
'formula' => 'fungsi_bangunan * (ip_permanen + ip_kompleksitas + (0.5 * ip_ketinggian))',
|
||||
'calculation' => "{$fungsi_bangunan} * ({$ip_permanen} + {$ip_kompleksitas} + (0.5 * {$ipKetinggian}))",
|
||||
'result' => $h13
|
||||
],
|
||||
'step_2_main' => [
|
||||
'formula' => '(1*D13*(N13*70350*H13*1))',
|
||||
'calculation' => "1 * {$floorArea} * ({$indeks_lokalitas} * {$base_value} * {$h13} * 1)",
|
||||
'result' => $main_calculation
|
||||
],
|
||||
'step_3_additional' => [
|
||||
'formula' => '($O$3*(1*D13*(N13*70350*H13*1)))',
|
||||
'calculation' => "{$additional_factor} * {$main_calculation}",
|
||||
'result' => $additional_calculation
|
||||
],
|
||||
'step_4_total' => [
|
||||
'formula' => 'main + additional',
|
||||
'calculation' => "{$main_calculation} + {$additional_calculation}",
|
||||
'result' => $total_retribution
|
||||
]
|
||||
],
|
||||
'formatted_results' => [
|
||||
'H13' => number_format($h13, 6),
|
||||
'main_calculation' => 'Rp ' . number_format($main_calculation, 2),
|
||||
'additional_calculation' => 'Rp ' . number_format($additional_calculation, 2),
|
||||
'total_result' => 'Rp ' . number_format($total_retribution, 2)
|
||||
]
|
||||
];
|
||||
|
||||
$this->info("📊 Calculation Breakdown:");
|
||||
$this->newLine();
|
||||
|
||||
// Show each step
|
||||
foreach ($breakdown['calculation_steps'] as $stepName => $step) {
|
||||
$this->info("🔸 " . strtoupper(str_replace('_', ' ', $stepName)));
|
||||
$this->line(" Formula: " . $step['formula']);
|
||||
$this->line(" Calculation: " . $step['calculation']);
|
||||
$this->line(" Result: " . (is_numeric($step['result']) ? number_format($step['result'], 6) : $step['result']));
|
||||
$this->newLine();
|
||||
$this->info(' ✓ Before ROUNDDOWN: ' . $rundown4['before_rounddown']);
|
||||
$this->info(' ✓ After ROUNDDOWN(4): ' . $rundown4['after_rounddown']);
|
||||
$this->info(' ✓ Basic Retribution: Rp ' . number_format($retribution['basic_amount']));
|
||||
$this->info(' ✓ Infrastructure: Rp ' . number_format($retribution['infrastructure_amount']));
|
||||
$this->info(' 💰 TOTAL: Rp ' . number_format($retribution['total_amount']));
|
||||
} else {
|
||||
$this->error(' ❌ Error: ' . $result1['error']);
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
$this->info("💰 Final Results:");
|
||||
$this->table(
|
||||
['Component', 'Value'],
|
||||
[
|
||||
['H13 (Floor Coefficient)', $breakdown['formatted_results']['H13']],
|
||||
['Main Calculation', $breakdown['formatted_results']['main_calculation']],
|
||||
['Additional (50%)', $breakdown['formatted_results']['additional_calculation']],
|
||||
['Total Retribution', $breakdown['formatted_results']['total_result']]
|
||||
]
|
||||
// Test 2: Usaha Besar
|
||||
$this->info('2. USAHA BESAR (3 Lantai, 200 m²)');
|
||||
|
||||
$result2 = $service->calculateRetribution(
|
||||
buildingFunctionId: 9, // USAHA_BESAR
|
||||
floorLevel: 3,
|
||||
luasBangunan: 200,
|
||||
indeksLokasi: 'tinggi',
|
||||
includeInfrastructure: true
|
||||
);
|
||||
|
||||
if ($result2['success']) {
|
||||
$rundown4 = $result2['calculation_breakdown']['rundown_4_calculation'];
|
||||
$retribution = $result2['calculation_breakdown']['retribution_calculation'];
|
||||
|
||||
$this->info(' ✓ Rundown 4 Result: ' . $rundown4['after_rounddown']);
|
||||
$this->info(' ✓ Basic: Rp ' . number_format($retribution['basic_amount']));
|
||||
$this->info(' ✓ Infrastructure: Rp ' . number_format($retribution['infrastructure_amount']));
|
||||
$this->info(' 💰 TOTAL: Rp ' . number_format($retribution['total_amount']));
|
||||
}
|
||||
$this->newLine();
|
||||
$this->info("🔍 Excel Formula Verification:");
|
||||
$this->line("Main Formula: =(1*D13*(N13*70350*H13*1))+(\$O\$3*(1*D13*(N13*70350*H13*1)))");
|
||||
$this->line("H13 Formula: =(\$E13*(\$F13+\$G13+(0.5*H\$3)))");
|
||||
|
||||
// Test with different floor numbers
|
||||
if ($this->confirm('Test with different floor numbers?')) {
|
||||
$this->testMultipleFloors($buildingFunction, $floorArea, $parameters);
|
||||
}
|
||||
// Test 3: Keagamaan (Free)
|
||||
$this->info('3. KEAGAMAAN (2 Lantai, 150 m²) - BEBAS RETRIBUSI');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test calculation with multiple floor numbers
|
||||
*/
|
||||
protected function testMultipleFloors(BuildingFunction $buildingFunction, float $floorArea, array $parameters)
|
||||
{
|
||||
$this->newLine();
|
||||
$this->info("🏢 Testing Multiple Floors:");
|
||||
|
||||
$tableData = [];
|
||||
$totalRetribution = 0;
|
||||
|
||||
for ($floor = 1; $floor <= 5; $floor++) {
|
||||
$floorHeightIndex = FloorHeightIndex::where('floor_number', $floor)->first();
|
||||
$ipKetinggian = $floorHeightIndex ? $floorHeightIndex->ip_ketinggian : 1.0;
|
||||
|
||||
// Calculate using Excel formula
|
||||
$fungsi_bangunan = $parameters['fungsi_bangunan'];
|
||||
$ip_permanen = $parameters['ip_permanen'];
|
||||
$ip_kompleksitas = $parameters['ip_kompleksitas'];
|
||||
$indeks_lokalitas = $parameters['indeks_lokalitas'];
|
||||
$base_value = 70350;
|
||||
$additional_factor = 0.5;
|
||||
|
||||
// Calculate H13 and result
|
||||
$H13 = $fungsi_bangunan * ($ip_permanen + $ip_kompleksitas + (0.5 * $ipKetinggian));
|
||||
$main_calc = 1 * $floorArea * ($indeks_lokalitas * $base_value * $H13 * 1);
|
||||
$additional_calc = $additional_factor * $main_calc;
|
||||
$result = $main_calc + $additional_calc;
|
||||
|
||||
$totalRetribution += $result;
|
||||
|
||||
$tableData[] = [
|
||||
"L{$floor}",
|
||||
$ipKetinggian,
|
||||
number_format($H13, 6),
|
||||
'Rp ' . number_format($result, 2)
|
||||
];
|
||||
}
|
||||
|
||||
$this->table(
|
||||
['Floor', 'IP Ketinggian', 'H13 Value', 'Retribution Amount'],
|
||||
$tableData
|
||||
$result3 = $service->calculateRetribution(
|
||||
buildingFunctionId: 1, // KEAGAMAAN
|
||||
floorLevel: 2,
|
||||
luasBangunan: 150,
|
||||
indeksLokasi: 'sedang',
|
||||
includeInfrastructure: true
|
||||
);
|
||||
|
||||
if ($result3['success']) {
|
||||
$this->info(' ✓ Rundown 4 Result: ' . $result3['results']['h5_rundown4']);
|
||||
$this->info(' 💸 RETRIBUSI BEBAS: Rp ' . number_format($result3['results']['total_retribution']));
|
||||
}
|
||||
$this->newLine();
|
||||
$this->info("🏗️ Total Building Retribution (5 floors): Rp " . number_format($totalRetribution, 2));
|
||||
$this->info("📏 Total Building Area: " . number_format($floorArea * 5, 2) . " m²");
|
||||
$this->info("💡 Average per m²: Rp " . number_format($totalRetribution / ($floorArea * 5), 2));
|
||||
|
||||
// Test 4: Multi-Floor Calculation
|
||||
$this->info('4. CAMPURAN BESAR - Multi Lantai (1-4 Lantai, 300 m²)');
|
||||
|
||||
$result4 = $service->calculateMultiFloorRetribution(
|
||||
buildingFunctionId: 7, // CAMPURAN_BESAR
|
||||
floors: [1, 2, 3, 4],
|
||||
luasBangunan: 300,
|
||||
indeksLokasi: 'tinggi'
|
||||
);
|
||||
|
||||
if ($result4['success']) {
|
||||
$this->info(' ✓ Per Floor Calculations:');
|
||||
foreach ($result4['floor_details'] as $floor => $detail) {
|
||||
$this->info(" Lantai {$floor}: H5={$detail['h5_rundown4']}, Total=Rp " . number_format($detail['total_retribution']));
|
||||
}
|
||||
$this->info(' 💰 TOTAL SEMUA LANTAI: Rp ' . number_format($result4['total_retribution']));
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
$this->info('=== RUNDOWN 4 VERIFICATION ===');
|
||||
$this->info('✅ Formula: =ROUNDDOWN(($E13*($F13+$G13+(0.5*I$3))),4)');
|
||||
$this->info('✅ ROUNDDOWN function with 4 decimal precision');
|
||||
$this->info('✅ Tarif Dasar: Rp 7.035.000');
|
||||
$this->info('✅ Infrastructure calculation: O3 * basic');
|
||||
$this->info('✅ Code simplified - unused formulas removed');
|
||||
$this->newLine();
|
||||
$this->info('🎉 RUNDOWN 4 Implementation is CLEAN and VERIFIED!');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
110
app/Models/BuildingFunctionFormulaConfig.php
Normal file
110
app/Models/BuildingFunctionFormulaConfig.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class BuildingFunctionFormulaConfig extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'building_function_id',
|
||||
'formula_id',
|
||||
'floor_level',
|
||||
'min_floor',
|
||||
'max_floor',
|
||||
'multiplier',
|
||||
'is_active',
|
||||
'priority',
|
||||
'notes',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'multiplier' => 'decimal:4',
|
||||
'is_active' => 'boolean',
|
||||
'min_floor' => 'integer',
|
||||
'max_floor' => 'integer',
|
||||
'floor_level' => 'integer',
|
||||
'priority' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relationship to BuildingFunction
|
||||
*/
|
||||
public function buildingFunction()
|
||||
{
|
||||
return $this->belongsTo(BuildingFunction::class, 'building_function_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship to MasterFormula
|
||||
*/
|
||||
public function formula()
|
||||
{
|
||||
return $this->belongsTo(MasterFormula::class, 'formula_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk konfigurasi aktif
|
||||
*/
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('is_active', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk mencari berdasarkan building function dan floor level
|
||||
*/
|
||||
public function scopeForBuildingAndFloor($query, $buildingFunctionId, $floorLevel)
|
||||
{
|
||||
return $query->where('building_function_id', $buildingFunctionId)
|
||||
->where(function($q) use ($floorLevel) {
|
||||
$q->where('floor_level', $floorLevel)
|
||||
->orWhere('floor_level', 0) // 0 = berlaku untuk semua lantai
|
||||
->orWhere(function($qq) use ($floorLevel) {
|
||||
$qq->whereNotNull('min_floor')
|
||||
->whereNotNull('max_floor')
|
||||
->where('min_floor', '<=', $floorLevel)
|
||||
->where('max_floor', '>=', $floorLevel);
|
||||
});
|
||||
})
|
||||
->orderBy('priority', 'desc')
|
||||
->orderBy('floor_level', 'desc'); // Prioritas: spesifik floor > range > semua lantai
|
||||
}
|
||||
|
||||
/**
|
||||
* Method untuk mendapatkan formula yang tepat untuk building function dan floor tertentu
|
||||
*/
|
||||
public static function getFormulaForBuildingAndFloor($buildingFunctionId, $floorLevel)
|
||||
{
|
||||
return self::active()
|
||||
->forBuildingAndFloor($buildingFunctionId, $floorLevel)
|
||||
->with('formula')
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method untuk check apakah floor level masuk dalam range
|
||||
*/
|
||||
public function isFloorInRange($floorLevel)
|
||||
{
|
||||
// Jika floor_level = 0, berlaku untuk semua lantai
|
||||
if ($this->floor_level == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Jika ada specific floor level
|
||||
if ($this->floor_level == $floorLevel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Jika ada range min-max
|
||||
if (!is_null($this->min_floor) && !is_null($this->max_floor)) {
|
||||
return $floorLevel >= $this->min_floor && $floorLevel <= $this->max_floor;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
32
app/Models/FormulaParameter.php
Normal file
32
app/Models/FormulaParameter.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class FormulaParameter extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'formula_id',
|
||||
'parameter_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relationship to MasterFormula
|
||||
*/
|
||||
public function formula()
|
||||
{
|
||||
return $this->belongsTo(MasterFormula::class, 'formula_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship to MasterParameter
|
||||
*/
|
||||
public function parameter()
|
||||
{
|
||||
return $this->belongsTo(MasterParameter::class, 'parameter_id');
|
||||
}
|
||||
}
|
||||
81
app/Models/MasterFormula.php
Normal file
81
app/Models/MasterFormula.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MasterFormula extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'formula_code',
|
||||
'formula_name',
|
||||
'formula_expression',
|
||||
'formula_category',
|
||||
'description',
|
||||
'usage_notes',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relationship to FormulaParameter (Many-to-Many dengan MasterParameter)
|
||||
*/
|
||||
public function formulaParameters()
|
||||
{
|
||||
return $this->hasMany(FormulaParameter::class, 'formula_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship to MasterParameter through FormulaParameter
|
||||
*/
|
||||
public function parameters()
|
||||
{
|
||||
return $this->belongsToMany(MasterParameter::class, 'formula_parameters', 'formula_id', 'parameter_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship to BuildingFunctionFormulaConfig
|
||||
*/
|
||||
public function buildingConfigs()
|
||||
{
|
||||
return $this->hasMany(BuildingFunctionFormulaConfig::class, 'formula_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk mencari berdasarkan kategori
|
||||
*/
|
||||
public function scopeByCategory($query, $category)
|
||||
{
|
||||
return $query->where('formula_category', $category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method untuk mendapatkan parameter yang diperlukan formula ini
|
||||
*/
|
||||
public function getRequiredParameters()
|
||||
{
|
||||
return $this->parameters()->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method untuk evaluate formula dengan parameter values
|
||||
*/
|
||||
public function evaluateFormula($parameterValues = [])
|
||||
{
|
||||
$expression = $this->formula_expression;
|
||||
|
||||
// Replace parameter codes dengan nilai actual
|
||||
foreach ($parameterValues as $parameterCode => $value) {
|
||||
$expression = str_replace('{' . $parameterCode . '}', $value, $expression);
|
||||
}
|
||||
|
||||
// Evaluasi mathematical expression (hati-hati dengan security!)
|
||||
// Untuk production, gunakan library yang aman seperti SymfonyExpressionLanguage
|
||||
try {
|
||||
return eval("return $expression;");
|
||||
} catch (Exception $e) {
|
||||
throw new \Exception("Error evaluating formula: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
55
app/Models/MasterParameter.php
Normal file
55
app/Models/MasterParameter.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MasterParameter extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'parameter_code',
|
||||
'parameter_name',
|
||||
'default_value',
|
||||
'unit',
|
||||
'description',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'default_value' => 'decimal:6',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relationship to FormulaParameter
|
||||
*/
|
||||
public function formulaParameters()
|
||||
{
|
||||
return $this->hasMany(FormulaParameter::class, 'parameter_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship to MasterFormula through FormulaParameter
|
||||
*/
|
||||
public function formulas()
|
||||
{
|
||||
return $this->belongsToMany(MasterFormula::class, 'formula_parameters', 'parameter_id', 'formula_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk mencari berdasarkan parameter code
|
||||
*/
|
||||
public function scopeByCode($query, $code)
|
||||
{
|
||||
return $query->where('parameter_code', $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method untuk mendapatkan nilai parameter dengan fallback ke default
|
||||
*/
|
||||
public function getValue($customValue = null)
|
||||
{
|
||||
return $customValue !== null ? $customValue : $this->default_value;
|
||||
}
|
||||
}
|
||||
180
app/Services/DynamicRetributionCalculationService.php
Normal file
180
app/Services/DynamicRetributionCalculationService.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\BuildingFunction;
|
||||
use App\Models\MasterParameter;
|
||||
|
||||
/**
|
||||
* Retribution Calculation Service - Rundown 4 Implementation
|
||||
*
|
||||
* Implementasi rumus Excel Rundown 4:
|
||||
* =ROUNDDOWN(($E13*($F13+$G13+(0.5*I$3))),4)
|
||||
* Retribusi = (1*D5*(N5*7035000*H5*1))+($O$3*(1*D5*(N5*7035000*H5*1)))
|
||||
*/
|
||||
class DynamicRetributionCalculationService
|
||||
{
|
||||
/**
|
||||
* Calculate retribution using Rundown 4 formula
|
||||
*/
|
||||
public function calculateRetribution($buildingFunctionId, $floorLevel, $luasBangunan, $indeksLokasi = 'sedang', $includeInfrastructure = true)
|
||||
{
|
||||
try {
|
||||
// Get parameters for this building function
|
||||
$parameters = $this->getParameterValues($buildingFunctionId, $floorLevel, $indeksLokasi);
|
||||
|
||||
// Step 1: Calculate Rundown 4 per floor value
|
||||
$h5 = $this->calculateRundown4($parameters);
|
||||
|
||||
// Step 2: Calculate basic retribution
|
||||
$basicRetribution = $parameters['koefisien_dasar'] * $luasBangunan *
|
||||
($parameters['indeks_lokalitas'] * $parameters['tarif_dasar'] * $h5 * $parameters['koefisien_dasar']);
|
||||
|
||||
// Step 3: Calculate infrastructure (optional)
|
||||
$infrastructureAmount = 0;
|
||||
$totalRetribution = $basicRetribution;
|
||||
|
||||
if ($includeInfrastructure) {
|
||||
$infrastructureAmount = $parameters['asumsi_prasarana'] * $basicRetribution;
|
||||
$totalRetribution = $basicRetribution + $infrastructureAmount;
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'building_function_id' => $buildingFunctionId,
|
||||
'floor_level' => $floorLevel,
|
||||
'luas_bangunan' => $luasBangunan,
|
||||
'indeks_lokalitas_type' => $indeksLokasi,
|
||||
'calculation_breakdown' => [
|
||||
'rundown_4_calculation' => [
|
||||
'excel_formula' => '=ROUNDDOWN(($E13*($F13+$G13+(0.5*I$3))),4)',
|
||||
'fungsi_bangunan' => $parameters['fungsi'],
|
||||
'ip_permanen' => $parameters['ip_permanen'],
|
||||
'ip_kompleksitas' => $parameters['ip_kompleksitas'],
|
||||
'multiplier_ketinggian' => $parameters['multiplier_ketinggian'],
|
||||
'ip_ketinggian' => $parameters['ip_ketinggian'],
|
||||
'before_rounddown' => $parameters['fungsi'] * ($parameters['ip_permanen'] + $parameters['ip_kompleksitas'] + ($parameters['multiplier_ketinggian'] * $parameters['ip_ketinggian'])),
|
||||
'after_rounddown' => $h5,
|
||||
'precision' => 4
|
||||
],
|
||||
'retribution_calculation' => [
|
||||
'basic_formula' => '1 * D5 * (N5 * 7035000 * H5 * 1)',
|
||||
'infrastructure_formula' => 'O3 * basic_retribution',
|
||||
'basic_amount' => $basicRetribution,
|
||||
'infrastructure_amount' => $infrastructureAmount,
|
||||
'total_amount' => $totalRetribution
|
||||
]
|
||||
],
|
||||
'results' => [
|
||||
'h5_rundown4' => $h5,
|
||||
'basic_retribution' => $basicRetribution,
|
||||
'infrastructure_amount' => $infrastructureAmount,
|
||||
'total_retribution' => $totalRetribution
|
||||
]
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'building_function_id' => $buildingFunctionId,
|
||||
'floor_level' => $floorLevel
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate multiple floors retribution
|
||||
*/
|
||||
public function calculateMultiFloorRetribution($buildingFunctionId, array $floors, $luasBangunan, $indeksLokasi = 'sedang')
|
||||
{
|
||||
$floorDetails = [];
|
||||
$totalRetribution = 0;
|
||||
|
||||
foreach ($floors as $floor) {
|
||||
$result = $this->calculateRetribution($buildingFunctionId, $floor, $luasBangunan, $indeksLokasi, true);
|
||||
|
||||
if ($result['success']) {
|
||||
$floorDetails[$floor] = $result['results'];
|
||||
$totalRetribution += $result['results']['total_retribution'];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'building_function_id' => $buildingFunctionId,
|
||||
'floors' => $floors,
|
||||
'luas_bangunan' => $luasBangunan,
|
||||
'indeks_lokalitas_type' => $indeksLokasi,
|
||||
'floor_details' => $floorDetails,
|
||||
'total_retribution' => $totalRetribution,
|
||||
'average_per_floor' => count($floors) > 0 ? $totalRetribution / count($floors) : 0
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Rundown 4 per-floor value with ROUNDDOWN
|
||||
* Formula: =ROUNDDOWN(($E13*($F13+$G13+(0.5*I$3))),4)
|
||||
*/
|
||||
private function calculateRundown4($parameters)
|
||||
{
|
||||
$calculation = $parameters['fungsi'] *
|
||||
($parameters['ip_permanen'] + $parameters['ip_kompleksitas'] +
|
||||
($parameters['multiplier_ketinggian'] * $parameters['ip_ketinggian']));
|
||||
|
||||
// Apply ROUNDDOWN with 4 decimal places
|
||||
return floor($calculation * 10000) / 10000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameter values for calculation
|
||||
*/
|
||||
private function getParameterValues($buildingFunctionId, $floorLevel, $indeksLokasi)
|
||||
{
|
||||
$buildingFunction = BuildingFunction::find($buildingFunctionId);
|
||||
if (!$buildingFunction) {
|
||||
throw new \Exception("Building function not found: {$buildingFunctionId}");
|
||||
}
|
||||
|
||||
$functionCode = strtolower($buildingFunction->code);
|
||||
|
||||
$lokalitasMapping = [
|
||||
'rendah' => 'indeks_lokalitas_rendah',
|
||||
'sedang' => 'indeks_lokalitas_sedang',
|
||||
'tinggi' => 'indeks_lokalitas_tinggi'
|
||||
];
|
||||
|
||||
$lokalitasParamCode = $lokalitasMapping[$indeksLokasi] ?? 'indeks_lokalitas_sedang';
|
||||
|
||||
$parameterCodes = [
|
||||
'tarif_dasar',
|
||||
'koefisien_dasar',
|
||||
'multiplier_ketinggian',
|
||||
'asumsi_prasarana',
|
||||
$lokalitasParamCode,
|
||||
"ip_ketinggian_{$floorLevel}",
|
||||
"fungsi_{$functionCode}",
|
||||
"ip_permanen_{$functionCode}",
|
||||
"ip_kompleksitas_{$functionCode}"
|
||||
];
|
||||
|
||||
$parameters = MasterParameter::whereIn('parameter_code', $parameterCodes)->get();
|
||||
|
||||
$values = [];
|
||||
foreach ($parameters as $param) {
|
||||
$values[$param->parameter_code] = $param->default_value;
|
||||
}
|
||||
|
||||
return [
|
||||
'tarif_dasar' => $values['tarif_dasar'] ?? 7035000,
|
||||
'koefisien_dasar' => $values['koefisien_dasar'] ?? 1,
|
||||
'multiplier_ketinggian' => $values['multiplier_ketinggian'] ?? 0.5,
|
||||
'asumsi_prasarana' => $values['asumsi_prasarana'] ?? 0.5,
|
||||
'indeks_lokalitas' => $values[$lokalitasParamCode] ?? 0.004,
|
||||
'ip_ketinggian' => $values["ip_ketinggian_{$floorLevel}"] ?? 1.0,
|
||||
'fungsi' => $values["fungsi_{$functionCode}"] ?? 0,
|
||||
'ip_permanen' => $values["ip_permanen_{$functionCode}"] ?? 0,
|
||||
'ip_kompleksitas' => $values["ip_kompleksitas_{$functionCode}"] ?? 0
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?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::create('master_parameters', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('parameter_code', 255)->unique()->comment('Kode unik parameter');
|
||||
$table->string('parameter_name', 255)->comment('Nama parameter');
|
||||
$table->decimal('default_value', 15, 6)->default(0.000000)->comment('Nilai default parameter');
|
||||
$table->string('unit', 50)->nullable()->comment('Satuan parameter');
|
||||
$table->text('description')->nullable()->comment('Deskripsi parameter');
|
||||
$table->timestamps();
|
||||
|
||||
// Add indexes for better performance
|
||||
$table->index('parameter_name', 'idx_master_parameters_name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('master_parameters');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
<?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::create('master_formulas', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('formula_code', 255)->unique()->comment('Kode unik formula');
|
||||
$table->string('formula_name', 255)->comment('Nama formula');
|
||||
$table->text('formula_expression')->comment('Formula matematika');
|
||||
$table->string('formula_category', 255)->nullable()->comment('Kategori formula');
|
||||
$table->text('description')->nullable()->comment('Deskripsi formula');
|
||||
$table->text('usage_notes')->nullable()->comment('Catatan penggunaan');
|
||||
$table->timestamps();
|
||||
|
||||
// Add indexes for better performance
|
||||
$table->index('formula_category', 'idx_master_formulas_category');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('master_formulas');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
<?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::create('formula_parameters', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('formula_id')->constrained('master_formulas')->onDelete('cascade')->comment('ID formula');
|
||||
$table->foreignId('parameter_id')->constrained('master_parameters')->onDelete('cascade')->comment('ID parameter');
|
||||
$table->timestamps();
|
||||
|
||||
// Composite unique constraint to prevent duplicate relations
|
||||
$table->unique(['formula_id', 'parameter_id'], 'unique_formula_parameter');
|
||||
|
||||
// Indexes for better performance
|
||||
$table->index('formula_id', 'idx_formula_parameters_formula');
|
||||
$table->index('parameter_id', 'idx_formula_parameters_parameter');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('formula_parameters');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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::create('building_function_formula_configs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('building_function_id')->constrained('building_functions')->onDelete('cascade')->comment('ID fungsi bangunan');
|
||||
$table->foreignId('formula_id')->constrained('master_formulas')->onDelete('cascade')->comment('ID formula yang digunakan');
|
||||
$table->integer('floor_level')->comment('Level lantai (1, 2, 3, dst. 0 untuk semua lantai)');
|
||||
$table->integer('min_floor')->nullable()->comment('Minimum lantai yang berlaku (opsional)');
|
||||
$table->integer('max_floor')->nullable()->comment('Maximum lantai yang berlaku (opsional)');
|
||||
$table->decimal('multiplier', 8, 4)->default(1.0000)->comment('Pengali khusus untuk lantai ini');
|
||||
$table->boolean('is_active')->default(true)->comment('Status aktif konfigurasi');
|
||||
$table->integer('priority')->default(0)->comment('Prioritas jika ada konflik (angka lebih besar = prioritas lebih tinggi)');
|
||||
$table->text('notes')->nullable()->comment('Catatan konfigurasi');
|
||||
$table->timestamps();
|
||||
|
||||
// Composite unique constraint untuk mencegah duplikasi konfigurasi
|
||||
$table->unique(['building_function_id', 'formula_id', 'floor_level'], 'unique_building_formula_floor');
|
||||
|
||||
// Indexes untuk performa
|
||||
$table->index(['building_function_id', 'floor_level'], 'idx_building_floor');
|
||||
$table->index(['building_function_id', 'is_active'], 'idx_building_active');
|
||||
$table->index(['floor_level', 'is_active'], 'idx_floor_active');
|
||||
$table->index('priority', 'idx_priority');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('building_function_formula_configs');
|
||||
}
|
||||
};
|
||||
216
database/seeders/BuildingFunctionFormulaConfigSeeder.php
Normal file
216
database/seeders/BuildingFunctionFormulaConfigSeeder.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\BuildingFunctionFormulaConfig;
|
||||
use App\Models\BuildingFunction;
|
||||
use App\Models\MasterFormula;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class BuildingFunctionFormulaConfigSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
// Mapping Building Function Codes to IDs (sesuai dengan BuildingFunctionSeeder)
|
||||
$buildingFunctionMapping = [
|
||||
'AGAMA' => 1, // Fungsi Keagamaan
|
||||
'SOSIAL_BUDAYA' => 2, // Fungsi Sosial Budaya
|
||||
'CAMPURAN_KECIL' => 6, // Campuran Kecil
|
||||
'CAMPURAN_BESAR' => 7, // Campuran Besar
|
||||
'USAHA_KECIL' => 8, // UMKM
|
||||
'USAHA_BESAR' => 9, // Usaha Besar (Non-Mikro)
|
||||
'HUNIAN_SEDERHANA' => 10, // Hunian Sederhana <100
|
||||
'HUNIAN_TIDAK_SEDERHANA' => 11, // Hunian Tidak Sederhana >100
|
||||
];
|
||||
|
||||
// Get Formula IDs (akan dibuat di MasterFormulaSeeder)
|
||||
$formulaMapping = [
|
||||
'BEBAS' => 'RETRIBUSI_BEBAS',
|
||||
'DASAR' => 'RETRIBUSI_DASAR',
|
||||
'LENGKAP' => 'RETRIBUSI_DENGAN_PRASARANA'
|
||||
];
|
||||
|
||||
// Configurations per Building Function dan Floor Level
|
||||
$configs = [];
|
||||
|
||||
// 1. FUNGSI KEAGAMAAN - Bebas Retribusi (semua lantai)
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['AGAMA'],
|
||||
'formula_code' => 'RETRIBUSI_BEBAS',
|
||||
'floor_level' => 0, // Berlaku untuk semua lantai
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => 'Bangunan keagamaan bebas retribusi untuk semua lantai'
|
||||
];
|
||||
|
||||
// 2. FUNGSI SOSIAL BUDAYA - Formula dengan parameter khusus
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['SOSIAL_BUDAYA'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "Sosial budaya lantai {$floor} - menggunakan parameter khusus sosial budaya"
|
||||
];
|
||||
}
|
||||
|
||||
// 3. CAMPURAN KECIL - Formula per lantai
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['CAMPURAN_KECIL'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "Campuran kecil lantai {$floor} - parameter fungsi 0.6"
|
||||
];
|
||||
}
|
||||
|
||||
// 4. CAMPURAN BESAR - Formula per lantai
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['CAMPURAN_BESAR'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "Campuran besar lantai {$floor} - parameter fungsi 0.8"
|
||||
];
|
||||
}
|
||||
|
||||
// 5. UMKM - Formula per lantai
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['USAHA_KECIL'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "UMKM lantai {$floor} - parameter fungsi 0.5"
|
||||
];
|
||||
}
|
||||
|
||||
// 6. USAHA BESAR - Formula per lantai
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['USAHA_BESAR'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "Usaha besar lantai {$floor} - parameter fungsi 0.7"
|
||||
];
|
||||
}
|
||||
|
||||
// 7. HUNIAN SEDERHANA - Formula khusus dengan IP Kompleksitas 0.3
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['HUNIAN_SEDERHANA'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "Hunian sederhana lantai {$floor} - parameter fungsi 0.15, IP kompleksitas 0.3"
|
||||
];
|
||||
}
|
||||
|
||||
// 8. HUNIAN TIDAK SEDERHANA - Formula standar
|
||||
for ($floor = 1; $floor <= 6; $floor++) {
|
||||
$configs[] = [
|
||||
'building_function_id' => $buildingFunctionMapping['HUNIAN_TIDAK_SEDERHANA'],
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'floor_level' => $floor,
|
||||
'min_floor' => null,
|
||||
'max_floor' => null,
|
||||
'multiplier' => 1.0000,
|
||||
'is_active' => true,
|
||||
'priority' => 1,
|
||||
'notes' => "Hunian tidak sederhana lantai {$floor} - parameter fungsi 0.17"
|
||||
];
|
||||
}
|
||||
|
||||
// Insert configurations
|
||||
foreach ($configs as $config) {
|
||||
// Get formula ID
|
||||
$formula = DB::table('master_formulas')
|
||||
->where('formula_code', $config['formula_code'])
|
||||
->first();
|
||||
|
||||
if ($formula) {
|
||||
DB::table('building_function_formula_configs')->updateOrInsert(
|
||||
[
|
||||
'building_function_id' => $config['building_function_id'],
|
||||
'formula_id' => $formula->id,
|
||||
'floor_level' => $config['floor_level']
|
||||
],
|
||||
[
|
||||
'min_floor' => $config['min_floor'],
|
||||
'max_floor' => $config['max_floor'],
|
||||
'multiplier' => $config['multiplier'],
|
||||
'is_active' => $config['is_active'],
|
||||
'priority' => $config['priority'],
|
||||
'notes' => $config['notes'],
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->command->info('Building Function Formula Configurations seeded successfully!');
|
||||
$this->command->info('=== CONFIGURATION SUMMARY ===');
|
||||
$this->command->info('Total configurations created: ' . count($configs));
|
||||
|
||||
// Summary per building function
|
||||
$summary = [];
|
||||
foreach ($configs as $config) {
|
||||
$buildingFunctionId = $config['building_function_id'];
|
||||
if (!isset($summary[$buildingFunctionId])) {
|
||||
$summary[$buildingFunctionId] = 0;
|
||||
}
|
||||
$summary[$buildingFunctionId]++;
|
||||
}
|
||||
|
||||
foreach ($buildingFunctionMapping as $code => $id) {
|
||||
$count = $summary[$id] ?? 0;
|
||||
$this->command->info("{$code}: {$count} configurations");
|
||||
}
|
||||
|
||||
$this->command->info('=== KEY FEATURES ===');
|
||||
$this->command->info('✓ Fungsi Keagamaan: Bebas retribusi semua lantai');
|
||||
$this->command->info('✓ Setiap fungsi bangunan memiliki parameter berbeda');
|
||||
$this->command->info('✓ Setiap lantai memiliki IP ketinggian berbeda');
|
||||
$this->command->info('✓ Hunian sederhana: IP kompleksitas khusus 0.3');
|
||||
$this->command->info('✓ Formula dapat disesuaikan per fungsi dan lantai');
|
||||
}
|
||||
}
|
||||
106
database/seeders/MasterFormulaSeeder.php
Normal file
106
database/seeders/MasterFormulaSeeder.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\MasterFormula;
|
||||
use App\Models\MasterParameter;
|
||||
use App\Models\FormulaParameter;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class MasterFormulaSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
// 1. Master Formulas
|
||||
$formulas = [
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_DASAR',
|
||||
'formula_name' => 'Formula Retribusi Dasar',
|
||||
'formula_expression' => '{koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_bangunan} * ({ip_permanen} + {ip_kompleksitas} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})',
|
||||
'formula_category' => 'basic',
|
||||
'description' => 'Formula dasar untuk perhitungan retribusi PBG tanpa prasarana',
|
||||
'usage_notes' => 'Menggunakan rumus: 1*D5*(N5*tarif_dasar*H5*1) dimana H5=E5*(F5+G5+(0.5*H3))'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_DENGAN_PRASARANA',
|
||||
'formula_name' => 'Formula Retribusi dengan Prasarana',
|
||||
'formula_expression' => '({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_bangunan} * ({ip_permanen} + {ip_kompleksitas} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})) + ({asumsi_prasarana} * ({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_bangunan} * ({ip_permanen} + {ip_kompleksitas} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})))',
|
||||
'formula_category' => 'complete',
|
||||
'description' => 'Formula lengkap retribusi PBG termasuk prasarana',
|
||||
'usage_notes' => 'Formula utama: (dasar) + (prasarana * dasar). Sesuai rumus Excel yang diberikan'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_BEBAS',
|
||||
'formula_name' => 'Formula Retribusi Bebas',
|
||||
'formula_expression' => '0',
|
||||
'formula_category' => 'free',
|
||||
'description' => 'Formula untuk bangunan yang bebas retribusi',
|
||||
'usage_notes' => 'Digunakan untuk bangunan keagamaan dan MBR'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_PER_LANTAI',
|
||||
'formula_name' => 'Formula Perhitungan per Lantai (H5)',
|
||||
'formula_expression' => '{fungsi_bangunan} * ({ip_permanen} + {ip_kompleksitas} + ({multiplier_ketinggian} * {ip_ketinggian}))',
|
||||
'formula_category' => 'component',
|
||||
'description' => 'Formula untuk menghitung nilai per lantai (H5 dalam Excel)',
|
||||
'usage_notes' => 'Rumus: E5*(F5+G5+(0.5*H3)) - komponen perhitungan per lantai'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_HUNIAN_SEDERHANA',
|
||||
'formula_name' => 'Formula Retribusi Hunian Sederhana',
|
||||
'formula_expression' => '({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_hunian_sederhana} * ({ip_permanen_hunian_sederhana} + {ip_kompleksitas_hunian_sederhana} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})) + ({asumsi_prasarana} * ({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_hunian_sederhana} * ({ip_permanen_hunian_sederhana} + {ip_kompleksitas_hunian_sederhana} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})))',
|
||||
'formula_category' => 'residential',
|
||||
'description' => 'Formula khusus untuk hunian sederhana dengan IP kompleksitas 0.3',
|
||||
'usage_notes' => 'Menggunakan parameter khusus hunian sederhana'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_HUNIAN_TIDAK_SEDERHANA',
|
||||
'formula_name' => 'Formula Retribusi Hunian Tidak Sederhana',
|
||||
'formula_expression' => '({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_hunian_tidak_sederhana} * ({ip_permanen_hunian_tidak_sederhana} + {ip_kompleksitas_hunian_tidak_sederhana} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})) + ({asumsi_prasarana} * ({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_hunian_tidak_sederhana} * ({ip_permanen_hunian_tidak_sederhana} + {ip_kompleksitas_hunian_tidak_sederhana} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})))',
|
||||
'formula_category' => 'residential',
|
||||
'description' => 'Formula khusus untuk hunian tidak sederhana',
|
||||
'usage_notes' => 'Menggunakan parameter khusus hunian tidak sederhana'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_SOSIAL_BUDAYA',
|
||||
'formula_name' => 'Formula Retribusi Sosial Budaya',
|
||||
'formula_expression' => '({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_sosial_budaya} * ({ip_permanen_sosial_budaya} + {ip_kompleksitas_sosial_budaya} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})) + ({asumsi_prasarana} * ({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_sosial_budaya} * ({ip_permanen_sosial_budaya} + {ip_kompleksitas_sosial_budaya} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})))',
|
||||
'formula_category' => 'social',
|
||||
'description' => 'Formula khusus untuk bangunan sosial budaya',
|
||||
'usage_notes' => 'Menggunakan parameter fungsi sosial budaya'
|
||||
],
|
||||
[
|
||||
'formula_code' => 'RETRIBUSI_USAHA',
|
||||
'formula_name' => 'Formula Retribusi Usaha',
|
||||
'formula_expression' => '({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_usaha_besar} * ({ip_permanen_usaha_besar} + {ip_kompleksitas_usaha_besar} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})) + ({asumsi_prasarana} * ({koefisien_dasar} * {luas_bangunan} * ({indeks_lokalitas} * {tarif_dasar} * ({fungsi_usaha_besar} * ({ip_permanen_usaha_besar} + {ip_kompleksitas_usaha_besar} + ({multiplier_ketinggian} * {ip_ketinggian}))) * {koefisien_dasar})))',
|
||||
'formula_category' => 'commercial',
|
||||
'description' => 'Formula khusus untuk bangunan usaha',
|
||||
'usage_notes' => 'Menggunakan parameter fungsi usaha besar'
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($formulas as $formula) {
|
||||
DB::table('master_formulas')->updateOrInsert(
|
||||
['formula_code' => $formula['formula_code']],
|
||||
array_merge($formula, [
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
$this->command->info('Master Formulas seeded successfully!');
|
||||
$this->command->info('=== FORMULA SUMMARY ===');
|
||||
foreach ($formulas as $formula) {
|
||||
$this->command->info($formula['formula_code'] . ': ' . $formula['formula_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
387
database/seeders/MasterParameterSeeder.php
Normal file
387
database/seeders/MasterParameterSeeder.php
Normal file
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\MasterParameter;
|
||||
use App\Models\BuildingFunction;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class MasterParameterSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
// 1. General Parameters (Parameter Umum)
|
||||
$generalParameters = [
|
||||
[
|
||||
'parameter_code' => 'luas_bangunan',
|
||||
'parameter_name' => 'Luas Bangunan',
|
||||
'default_value' => 0.000000,
|
||||
'unit' => 'm²',
|
||||
'description' => 'Luas total bangunan dalam meter persegi'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'tarif_dasar',
|
||||
'parameter_name' => 'Tarif Dasar',
|
||||
'default_value' => 7035000.000000,
|
||||
'unit' => 'Rupiah',
|
||||
'description' => 'Tarif dasar retribusi per meter persegi (7.035.000)'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'koefisien_dasar',
|
||||
'parameter_name' => 'Koefisien Dasar',
|
||||
'default_value' => 1.000000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Koefisien dasar perhitungan'
|
||||
]
|
||||
];
|
||||
|
||||
// 2. IP Ketinggian Parameters per Lantai (Data dari tabel)
|
||||
$floorHeightParameters = [
|
||||
[
|
||||
'parameter_code' => 'ip_ketinggian_1',
|
||||
'parameter_name' => 'IP Ketinggian Lantai 1',
|
||||
'default_value' => 1.000000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks ketinggian untuk lantai 1'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_ketinggian_2',
|
||||
'parameter_name' => 'IP Ketinggian Lantai 2',
|
||||
'default_value' => 1.090000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks ketinggian untuk lantai 2'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_ketinggian_3',
|
||||
'parameter_name' => 'IP Ketinggian Lantai 3',
|
||||
'default_value' => 1.120000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks ketinggian untuk lantai 3'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_ketinggian_4',
|
||||
'parameter_name' => 'IP Ketinggian Lantai 4',
|
||||
'default_value' => 1.135000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks ketinggian untuk lantai 4'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_ketinggian_5',
|
||||
'parameter_name' => 'IP Ketinggian Lantai 5',
|
||||
'default_value' => 1.162000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks ketinggian untuk lantai 5'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_ketinggian_6',
|
||||
'parameter_name' => 'IP Ketinggian Lantai 6',
|
||||
'default_value' => 1.197000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks ketinggian untuk lantai 6'
|
||||
]
|
||||
];
|
||||
|
||||
// 3. Building Function Specific Parameters (Data dari tabel)
|
||||
$buildingFunctionParameters = [
|
||||
// FUNGSI KEAGAMAAN - Bebas retribusi
|
||||
[
|
||||
'parameter_code' => 'fungsi_keagamaan',
|
||||
'parameter_name' => 'Fungsi Bangunan Keagamaan',
|
||||
'default_value' => 0.000000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi bangunan keagamaan (bebas retribusi)'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_keagamaan',
|
||||
'parameter_name' => 'IP Permanen Keagamaan',
|
||||
'default_value' => 0.000000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk bangunan keagamaan'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_keagamaan',
|
||||
'parameter_name' => 'IP Kompleksitas Keagamaan',
|
||||
'default_value' => 0.000000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk bangunan keagamaan'
|
||||
],
|
||||
|
||||
// FUNGSI SOSIAL BUDAYA - 0.3
|
||||
[
|
||||
'parameter_code' => 'fungsi_sosial_budaya',
|
||||
'parameter_name' => 'Fungsi Bangunan Sosial Budaya',
|
||||
'default_value' => 0.300000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi bangunan sosial budaya'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_sosial_budaya',
|
||||
'parameter_name' => 'IP Permanen Sosial Budaya',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk bangunan sosial budaya'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_sosial_budaya',
|
||||
'parameter_name' => 'IP Kompleksitas Sosial Budaya',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk bangunan sosial budaya'
|
||||
],
|
||||
|
||||
// CAMPURAN KECIL - 0.6
|
||||
[
|
||||
'parameter_code' => 'fungsi_campuran_kecil',
|
||||
'parameter_name' => 'Fungsi Bangunan Campuran Kecil',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi bangunan campuran kecil'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_campuran_kecil',
|
||||
'parameter_name' => 'IP Permanen Campuran Kecil',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk bangunan campuran kecil'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_campuran_kecil',
|
||||
'parameter_name' => 'IP Kompleksitas Campuran Kecil',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk bangunan campuran kecil'
|
||||
],
|
||||
|
||||
// CAMPURAN BESAR - 0.8
|
||||
[
|
||||
'parameter_code' => 'fungsi_campuran_besar',
|
||||
'parameter_name' => 'Fungsi Bangunan Campuran Besar',
|
||||
'default_value' => 0.800000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi bangunan campuran besar'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_campuran_besar',
|
||||
'parameter_name' => 'IP Permanen Campuran Besar',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk bangunan campuran besar'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_campuran_besar',
|
||||
'parameter_name' => 'IP Kompleksitas Campuran Besar',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk bangunan campuran besar'
|
||||
],
|
||||
|
||||
// UMKM - 0.5
|
||||
[
|
||||
'parameter_code' => 'fungsi_umkm',
|
||||
'parameter_name' => 'Fungsi Bangunan UMKM',
|
||||
'default_value' => 0.500000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi bangunan UMKM'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_umkm',
|
||||
'parameter_name' => 'IP Permanen UMKM',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk bangunan UMKM'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_umkm',
|
||||
'parameter_name' => 'IP Kompleksitas UMKM',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk bangunan UMKM'
|
||||
],
|
||||
|
||||
// USAHA BESAR - 0.7
|
||||
[
|
||||
'parameter_code' => 'fungsi_usaha_besar',
|
||||
'parameter_name' => 'Fungsi Bangunan Usaha Besar',
|
||||
'default_value' => 0.700000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi bangunan usaha besar'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_usaha_besar',
|
||||
'parameter_name' => 'IP Permanen Usaha Besar',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk bangunan usaha besar'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_usaha_besar',
|
||||
'parameter_name' => 'IP Kompleksitas Usaha Besar',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk bangunan usaha besar'
|
||||
],
|
||||
|
||||
// HUNIAN SEDERHANA - 0.15
|
||||
[
|
||||
'parameter_code' => 'fungsi_hunian_sederhana',
|
||||
'parameter_name' => 'Fungsi Hunian Sederhana',
|
||||
'default_value' => 0.150000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi hunian sederhana'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_hunian_sederhana',
|
||||
'parameter_name' => 'IP Permanen Hunian Sederhana',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk hunian sederhana'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_hunian_sederhana',
|
||||
'parameter_name' => 'IP Kompleksitas Hunian Sederhana',
|
||||
'default_value' => 0.300000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk hunian sederhana (0.3)'
|
||||
],
|
||||
|
||||
// HUNIAN TIDAK SEDERHANA - 0.17
|
||||
[
|
||||
'parameter_code' => 'fungsi_hunian_tidak_sederhana',
|
||||
'parameter_name' => 'Fungsi Hunian Tidak Sederhana',
|
||||
'default_value' => 0.170000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Parameter fungsi hunian tidak sederhana'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_permanen_hunian_tidak_sederhana',
|
||||
'parameter_name' => 'IP Permanen Hunian Tidak Sederhana',
|
||||
'default_value' => 0.400000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Permanen untuk hunian tidak sederhana'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'ip_kompleksitas_hunian_tidak_sederhana',
|
||||
'parameter_name' => 'IP Kompleksitas Hunian Tidak Sederhana',
|
||||
'default_value' => 0.600000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'IP Kompleksitas untuk hunian tidak sederhana'
|
||||
]
|
||||
];
|
||||
|
||||
// 4. Indeks Lokalitas Parameters
|
||||
$localityParameters = [
|
||||
[
|
||||
'parameter_code' => 'indeks_lokalitas_03',
|
||||
'parameter_name' => 'Indeks Lokalitas 0.3%',
|
||||
'default_value' => 0.003000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks lokalitas 0.3% (untuk bangunan tertentu)'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'indeks_lokalitas_04',
|
||||
'parameter_name' => 'Indeks Lokalitas 0.4%',
|
||||
'default_value' => 0.004000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks lokalitas 0.4% (untuk hunian sederhana dan tidak sederhana)'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'indeks_lokalitas_05',
|
||||
'parameter_name' => 'Indeks Lokalitas 0.5%',
|
||||
'default_value' => 0.005000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Indeks lokalitas 0.5% (untuk bangunan komersial)'
|
||||
]
|
||||
];
|
||||
|
||||
// 5. Multiplier Parameters
|
||||
$multiplierParameters = [
|
||||
[
|
||||
'parameter_code' => 'multiplier_prasarana',
|
||||
'parameter_name' => 'Multiplier Prasarana',
|
||||
'default_value' => 0.500000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Multiplier untuk perhitungan prasarana (50%)'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'multiplier_ketinggian',
|
||||
'parameter_name' => 'Multiplier Ketinggian',
|
||||
'default_value' => 0.500000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Multiplier untuk indeks ketinggian dalam formula (0.5)'
|
||||
]
|
||||
];
|
||||
|
||||
// 4. Additional Parameters (Parameter Tambahan)
|
||||
$additionalParameters = [
|
||||
[
|
||||
'parameter_code' => 'asumsi_prasarana',
|
||||
'parameter_name' => 'Asumsi Prasarana',
|
||||
'default_value' => 0.500000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Persentase asumsi prasarana dalam perhitungan retribusi'
|
||||
],
|
||||
[
|
||||
'parameter_code' => 'multiplier_ketinggian',
|
||||
'parameter_name' => 'Multiplier Ketinggian',
|
||||
'default_value' => 0.500000,
|
||||
'unit' => 'decimal',
|
||||
'description' => 'Multiplier untuk perhitungan ketinggian (0.5 dalam rumus Excel)'
|
||||
]
|
||||
];
|
||||
|
||||
// Combine all parameters
|
||||
$allParameters = array_merge(
|
||||
$generalParameters,
|
||||
$floorHeightParameters,
|
||||
$buildingFunctionParameters,
|
||||
$localityParameters,
|
||||
$multiplierParameters,
|
||||
$additionalParameters
|
||||
);
|
||||
|
||||
// Insert parameters
|
||||
foreach ($allParameters as $param) {
|
||||
DB::table('master_parameters')->updateOrInsert(
|
||||
['parameter_code' => $param['parameter_code']],
|
||||
array_merge($param, [
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
// Summary output
|
||||
$this->command->info('Master Parameters seeded successfully!');
|
||||
$this->command->info('=== SUMMARY ===');
|
||||
$this->command->info('General Parameters: ' . count($generalParameters));
|
||||
$this->command->info('Floor Height Parameters: ' . count($floorHeightParameters));
|
||||
$this->command->info('Building Function Parameters: ' . count($buildingFunctionParameters));
|
||||
$this->command->info('Locality Parameters: ' . count($localityParameters));
|
||||
$this->command->info('Multiplier Parameters: ' . count($multiplierParameters));
|
||||
$this->command->info('Additional Parameters: ' . count($additionalParameters));
|
||||
$this->command->info('Total Parameters: ' . count($allParameters));
|
||||
|
||||
// Display parameter mapping
|
||||
$this->command->info('=== BUILDING FUNCTION PARAMETER MAPPING ===');
|
||||
$this->command->info('KEAGAMAAN: Fungsi=0.000, IP_Permanen=0.000, IP_Kompleksitas=0.000');
|
||||
$this->command->info('SOSIAL_BUDAYA: Fungsi=0.300, IP_Permanen=0.400, IP_Kompleksitas=0.600');
|
||||
$this->command->info('CAMPURAN_KECIL: Fungsi=0.600, IP_Permanen=0.400, IP_Kompleksitas=0.600');
|
||||
$this->command->info('CAMPURAN_BESAR: Fungsi=0.800, IP_Permanen=0.400, IP_Kompleksitas=0.600');
|
||||
$this->command->info('UMKM: Fungsi=0.500, IP_Permanen=0.400, IP_Kompleksitas=0.600');
|
||||
$this->command->info('USAHA_BESAR: Fungsi=0.700, IP_Permanen=0.400, IP_Kompleksitas=0.600');
|
||||
$this->command->info('HUNIAN_SEDERHANA: Fungsi=0.150, IP_Permanen=0.400, IP_Kompleksitas=0.300');
|
||||
$this->command->info('HUNIAN_TIDAK_SEDERHANA: Fungsi=0.170, IP_Permanen=0.400, IP_Kompleksitas=0.600');
|
||||
|
||||
$this->command->info('=== IP KETINGGIAN PER LANTAI ===');
|
||||
$this->command->info('Lantai 1: 1.000, Lantai 2: 1.090, Lantai 3: 1.120');
|
||||
$this->command->info('Lantai 4: 1.135, Lantai 5: 1.162, Lantai 6: 1.197');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user