*/ 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']; protected $casts = [ 'area' => 'decimal:6', 'land_area' => 'decimal:6', 'site_bcr' => 'decimal:6', 'number_of_floors' => 'integer', 'date' => 'date' ]; /** * Retribution proposals relationship (1:many) */ public function retributionProposals(): HasMany { return $this->hasMany(RetributionProposal::class); } /** * Building function relationship (if building_function becomes FK in future) */ public function buildingFunctionRelation(): BelongsTo { return $this->belongsTo(BuildingFunction::class, 'building_function_id'); } /** * Check if spatial planning has retribution proposals */ public function hasRetributionProposals(): bool { return $this->retributionProposals()->exists(); } /** * Get latest retribution proposal */ public function getLatestRetributionProposal() { return $this->retributionProposals()->latest()->first(); } /** * Get all retribution proposals */ public function getAllRetributionProposals() { return $this->retributionProposals()->get(); } /** * 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); } /** * Scope: Without retribution proposals */ public function scopeWithoutRetributionProposals($query) { return $query->whereDoesntHave('retributionProposals'); } /** * Scope: With retribution proposals */ public function scopeWithRetributionProposals($query) { return $query->whereHas('retributionProposals'); } }