create service count floor level and retributions
This commit is contained in:
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
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user