Files
sibedas/app/Models/SpatialPlanning.php
2025-08-19 18:15:58 +07:00

243 lines
7.6 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Models;
use App\Traits\HasRetributionCalculation;
use Illuminate\Database\Eloquent\Model;
/**
* Class SpatialPlanning
*
* @property $id
* @property $created_at
* @property $updated_at
* @property $name
* @property $kbli
* @property $activities
* @property $area
* @property $location
* @property $number
* @property $date
*
* @package App
* @mixin \Illuminate\Database\Eloquent\Builder
*/
class SpatialPlanning extends Model
{
use HasRetributionCalculation;
protected $perPage = 20;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = ['name', 'kbli', 'activities', 'area', 'location', 'number', 'date', 'no_tapak', 'no_skkl', 'no_ukl', 'building_function', 'sub_building_function', 'number_of_floors', 'land_area', 'site_bcr', 'is_terbit'];
protected $casts = [
'area' => 'decimal:6',
'land_area' => 'decimal:6',
'site_bcr' => 'decimal:6',
'number_of_floors' => 'integer',
'date' => 'date',
'is_terbit' => 'boolean'
];
protected $appends = [
'calculated_retribution',
'formatted_retribution',
'is_business_type',
'calculation_details',
'old_calculation_amount',
'calculation_source'
];
/**
* Get building function text for detection
*/
public function getBuildingFunctionText(): string
{
return $this->building_function ?? $this->activities ?? '';
}
/**
* Get area for calculation (prioritize area, fallback to land_area)
*/
public function getCalculationArea(): float
{
return (float) ($this->area ?? $this->land_area ?? 0);
}
/**
* Get calculated retribution amount
* Priority: Manual calculation (new formula) > Active calculation (old system)
*/
public function getCalculatedRetributionAttribute(): float
{
try {
// PRIORITY 1: Use new manual formula (LUAS LAHAN × BCR × HARGA SATUAN)
$manualCalculation = $this->calculateRetributionManually();
// If manual calculation is valid (> 0), use it
if ($manualCalculation > 0) {
return $manualCalculation;
}
// PRIORITY 2: Fallback to active retribution calculation if exists
$activeCalculation = $this->activeRetributionCalculation;
if ($activeCalculation && $activeCalculation->retributionCalculation) {
return (float) $activeCalculation->retributionCalculation->retribution_amount;
}
// PRIORITY 3: Return 0 if nothing works
return 0.0;
} catch (\Exception $e) {
\Log::warning('Failed to calculate retribution for SpatialPlanning ID: ' . $this->id, [
'error' => $e->getMessage(),
'spatial_planning' => $this->toArray()
]);
return 0.0;
}
}
/**
* Manual calculation based on area and building function
* Formula: LUAS LAHAN × BCR × HARGA SATUAN
* NON USAHA: 16,000 per m2
* USAHA: 44,300 per m2
*/
private function calculateRetributionManually(): float
{
// Get land area (luas lahan)
$landArea = (float) ($this->land_area ?? 0);
// Get BCR (Building Coverage Ratio) - convert from percentage to decimal
$bcrPercentage = (float) ($this->site_bcr ?? 0);
$bcr = $bcrPercentage / 100; // Convert percentage to decimal (24.49% -> 0.2449)
if ($landArea <= 0 || $bcr <= 0) {
return 0.0;
}
// Determine if this is business (USAHA) or non-business (NON USAHA)
$isBusiness = $this->isBusinessType();
// Set unit price based on business type
$unitPrice = $isBusiness ? 44300 : 16000;
// Calculate: LUAS LAHAN × BCR (as decimal) × HARGA SATUAN
$calculatedAmount = $landArea * $bcr * $unitPrice;
return $calculatedAmount;
}
/**
* Determine if this spatial planning is for business purposes
*/
private function isBusinessType(): bool
{
$buildingFunction = strtolower($this->building_function ?? $this->activities ?? '');
// Business keywords
$businessKeywords = [
'usaha', 'dagang', 'perdagangan', 'komersial', 'commercial', 'bisnis', 'business',
'toko', 'warung', 'pasar', 'kios', 'mall', 'plaza', 'supermarket', 'department',
'hotel', 'resort', 'restoran', 'restaurant', 'cafe', 'kantor', 'perkantoran', 'office',
'industri', 'pabrik', 'gudang', 'warehouse', 'manufacturing', 'produksi',
'bengkel', 'workshop', 'showroom', 'dealer', 'apotek', 'pharmacy', 'klinik swasta',
'rumah sakit swasta', 'bank', 'atm', 'money changer', 'asuransi', 'leasing',
'rental', 'sewa', 'jasa', 'service', 'salon', 'spa', 'fitness', 'gym',
'tempat usaha', 'fungsi usaha', 'kegiatan usaha', 'bangunan usaha'
];
// Check if any business keyword is found
foreach ($businessKeywords as $keyword) {
if (str_contains($buildingFunction, $keyword)) {
return true;
}
}
// Non-business (default)
return false;
}
/**
* Get formatted retribution amount for display
*/
public function getFormattedRetributionAttribute(): string
{
$amount = $this->calculated_retribution;
return number_format($amount, 0, ',', '.');
}
/**
* Check if this is business type
*/
public function getIsBusinessTypeAttribute(): bool
{
return $this->isBusinessType();
}
/**
* Get calculation details for transparency
*/
public function getCalculationDetailsAttribute(): array
{
$landArea = (float) ($this->land_area ?? 0);
$bcrPercentage = (float) ($this->site_bcr ?? 0);
$bcr = $bcrPercentage / 100; // Convert to decimal
$isBusiness = $this->isBusinessType();
$unitPrice = $isBusiness ? 44300 : 16000;
$calculatedAmount = $landArea * $bcr * $unitPrice;
return [
'formula' => 'LUAS LAHAN × BCR (decimal) × HARGA SATUAN',
'land_area' => $landArea,
'bcr_percentage' => $bcrPercentage,
'bcr_decimal' => $bcr,
'business_type' => $isBusiness ? 'USAHA' : 'NON USAHA',
'unit_price' => $unitPrice,
'calculation' => "{$landArea} × {$bcr} × {$unitPrice}",
'result' => $calculatedAmount,
'building_function' => $this->building_function ?? $this->activities ?? 'N/A'
];
}
/**
* Get old calculation amount from database
*/
public function getOldCalculationAmountAttribute(): float
{
$activeCalculation = $this->activeRetributionCalculation;
if ($activeCalculation && $activeCalculation->retributionCalculation) {
return (float) $activeCalculation->retributionCalculation->retribution_amount;
}
return 0.0;
}
/**
* Get calculation source info
*/
public function getCalculationSourceAttribute(): string
{
$manualCalculation = $this->calculateRetributionManually();
$hasActiveCalculation = $this->hasActiveRetributionCalculation();
if ($manualCalculation > 0) {
return $hasActiveCalculation ? 'NEW_FORMULA' : 'NEW_FORMULA_ONLY';
} elseif ($hasActiveCalculation) {
return 'OLD_DATABASE';
}
return 'NONE';
}
}