webmoney/backend/app/Models/Category.php

154 lines
3.3 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model
{
use HasFactory, SoftDeletes;
/**
* Tipos de categoria
*/
public const TYPE_INCOME = 'income';
public const TYPE_EXPENSE = 'expense';
public const TYPE_BOTH = 'both';
public const TYPES = [
self::TYPE_INCOME => 'Receita',
self::TYPE_EXPENSE => 'Despesa',
self::TYPE_BOTH => 'Ambos',
];
protected $fillable = [
'user_id',
'parent_id',
'name',
'type',
'description',
'color',
'icon',
'order',
'is_active',
'is_system',
];
protected $casts = [
'order' => 'integer',
'is_active' => 'boolean',
'is_system' => 'boolean',
];
/**
* Relação com o usuário
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* Relação com a categoria pai
*/
public function parent(): BelongsTo
{
return $this->belongsTo(Category::class, 'parent_id');
}
/**
* Relação com as sub-categorias (filhas)
*/
public function children(): HasMany
{
return $this->hasMany(Category::class, 'parent_id');
}
/**
* Relação com as sub-categorias ativas
*/
public function activeChildren(): HasMany
{
return $this->hasMany(Category::class, 'parent_id')->where('is_active', true);
}
/**
* Relação com as palavras-chave
*/
public function keywords(): HasMany
{
return $this->hasMany(CategoryKeyword::class);
}
/**
* Relação com as palavras-chave ativas
*/
public function activeKeywords(): HasMany
{
return $this->hasMany(CategoryKeyword::class)->where('is_active', true);
}
/**
* Scope para categorias ativas
*/
public function scopeActive($query)
{
return $query->where('is_active', true);
}
/**
* Scope para categorias de um tipo específico
*/
public function scopeOfType($query, string $type)
{
return $query->where('type', $type)->orWhere('type', self::TYPE_BOTH);
}
/**
* Scope para categorias raiz (sem pai)
*/
public function scopeRoot($query)
{
return $query->whereNull('parent_id');
}
/**
* Scope para sub-categorias (com pai)
*/
public function scopeChildren($query)
{
return $query->whereNotNull('parent_id');
}
/**
* Retorna o nome legível do tipo
*/
public function getTypeNameAttribute(): string
{
return self::TYPES[$this->type] ?? $this->type;
}
/**
* Verifica se é uma categoria raiz
*/
public function isRoot(): bool
{
return $this->parent_id === null;
}
/**
* Retorna o caminho completo da categoria (Pai > Filho)
*/
public function getFullPathAttribute(): string
{
if ($this->parent) {
return $this->parent->name . ' > ' . $this->name;
}
return $this->name;
}
}