'integer' ]; /** * Building function relationship (n:1) */ public function buildingFunction(): BelongsTo { return $this->belongsTo(BuildingFunction::class); } /** * Retribution proposals relationship (1:n) */ public function retributionProposals(): HasMany { return $this->hasMany(RetributionProposal::class); } /** * Scope: By floor number */ public function scopeByFloor($query, int $floorNumber) { return $query->where('floor_number', $floorNumber); } /** * Execute formula calculation with parameters and IP ketinggian */ public function calculate(float $luasBangunan, array $parameters, float $ipKetinggian): float { // Extract parameters $fungsi_bangunan = $parameters['fungsi_bangunan'] ?? 0; $ip_permanen = $parameters['ip_permanen'] ?? 0; $ip_kompleksitas = $parameters['ip_kompleksitas'] ?? 0; $indeks_lokalitas = $parameters['indeks_lokalitas'] ?? 0; // Calculate H13 (floor coefficient) using Excel formula $h13 = $fungsi_bangunan * ($ip_permanen + $ip_kompleksitas + (0.5 * $ipKetinggian)); // Calculate full retribution using Excel formula $baseValue = 70350; $additionalFactor = 0.5; // Main calculation: (1*D13*(N13*70350*H13*1)) $mainCalculation = 1 * $luasBangunan * ($indeks_lokalitas * $baseValue * $h13 * 1); // Additional calculation: ($O$3*(1*D13*(N13*70350*H13*1))) $additionalCalculation = $additionalFactor * $mainCalculation; // Total: main + additional return $mainCalculation + $additionalCalculation; } /** * Get formula with parameter placeholders replaced for display */ public function getDisplayFormula(array $parameters = []): string { $formula = $this->formula_expression; if (!empty($parameters)) { foreach ($parameters as $key => $value) { $formula = str_replace($key, "({$key}={$value})", $formula); } } return $formula; } /** * Check if this formula applies to given floor number */ public function appliesTo(int $floorNumber): bool { // If floor_number is 0, formula applies to all floors if ($this->floor_number === 0) { return true; } // Otherwise, exact match required return $this->floor_number == $floorNumber; } /** * Get human readable floor description */ public function getFloorDescription(): string { if ($this->floor_number === 0) { return 'Semua lantai'; } return "Lantai {$this->floor_number}"; } /** * Get default formula expression */ public static function getDefaultFormula(): string { return '(fungsi_bangunan * (ip_permanen + ip_kompleksitas + (0.5 * ip_ketinggian)))'; } /** * Validate formula expression syntax */ public function validateFormula(): bool { // Basic validation - check if formula contains required variables $requiredVariables = ['fungsi_bangunan', 'ip_permanen', 'ip_kompleksitas', 'ip_ketinggian']; foreach ($requiredVariables as $variable) { if (strpos($this->formula_expression, $variable) === false) { return false; } } return true; } /** * Get calculation breakdown for debugging */ public function getCalculationBreakdown(float $luasBangunan, array $parameters, float $ipKetinggian): array { // Extract parameters $fungsi_bangunan = $parameters['fungsi_bangunan'] ?? 0; $ip_permanen = $parameters['ip_permanen'] ?? 0; $ip_kompleksitas = $parameters['ip_kompleksitas'] ?? 0; $indeks_lokalitas = $parameters['indeks_lokalitas'] ?? 0; // Calculate H13 (floor coefficient) $h13 = $fungsi_bangunan * ($ip_permanen + $ip_kompleksitas + (0.5 * $ipKetinggian)); // Calculate components $baseValue = 70350; $additionalFactor = 0.5; $mainCalculation = 1 * $luasBangunan * ($indeks_lokalitas * $baseValue * $h13 * 1); $additionalCalculation = $additionalFactor * $mainCalculation; $totalCalculation = $mainCalculation + $additionalCalculation; return [ 'input_parameters' => [ 'luas_bangunan' => $luasBangunan, 'fungsi_bangunan' => $fungsi_bangunan, 'ip_permanen' => $ip_permanen, 'ip_kompleksitas' => $ip_kompleksitas, 'ip_ketinggian' => $ipKetinggian, 'indeks_lokalitas' => $indeks_lokalitas, 'base_value' => $baseValue, 'additional_factor' => $additionalFactor ], 'calculation_steps' => [ 'h13_calculation' => [ 'formula' => 'fungsi_bangunan * (ip_permanen + ip_kompleksitas + (0.5 * ip_ketinggian))', 'calculation' => "{$fungsi_bangunan} * ({$ip_permanen} + {$ip_kompleksitas} + (0.5 * {$ipKetinggian}))", 'result' => $h13 ], 'main_calculation' => [ 'formula' => '1 * luas_bangunan * (indeks_lokalitas * base_value * h13 * 1)', 'calculation' => "1 * {$luasBangunan} * ({$indeks_lokalitas} * {$baseValue} * {$h13} * 1)", 'result' => $mainCalculation ], 'additional_calculation' => [ 'formula' => 'additional_factor * main_calculation', 'calculation' => "{$additionalFactor} * {$mainCalculation}", 'result' => $additionalCalculation ], 'total_calculation' => [ 'formula' => 'main_calculation + additional_calculation', 'calculation' => "{$mainCalculation} + {$additionalCalculation}", 'result' => $totalCalculation ] ], 'formatted_results' => [ 'h13' => number_format($h13, 6), 'main_calculation' => 'Rp ' . number_format($mainCalculation, 2), 'additional_calculation' => 'Rp ' . number_format($additionalCalculation, 2), 'total_calculation' => 'Rp ' . number_format($totalCalculation, 2) ] ]; } /** * Check if this formula has been used in any proposals */ public function hasProposals(): bool { return $this->retributionProposals()->exists(); } /** * Get total amount calculated using this formula */ public function getTotalCalculatedAmount(): float { return $this->retributionProposals()->sum('total_retribution_amount'); } /** * Get count of proposals using this formula */ public function getProposalCount(): int { return $this->retributionProposals()->count(); } }