webmoney/backend/app/Models/Plan.php
marco 54cccdd095 refactor: migração para desenvolvimento direto no servidor
- Removido README.md padrão do Laravel (backend)
- Removidos scripts de deploy (não mais necessários)
- Atualizado copilot-instructions.md para novo fluxo
- Adicionada documentação de auditoria do servidor
- Sincronizado código de produção com repositório

Novo workflow:
- Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney)
- Mudanças PHP são instantâneas
- Mudanças React requerem 'npm run build'
- Commit após validação funcional
2025-12-19 11:45:32 +01:00

163 lines
3.8 KiB
PHP
Executable File

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Plan extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',
'description',
'price',
'currency',
'billing_period',
'trial_days',
'features',
'limits',
'is_active',
'is_featured',
'is_free',
'sort_order',
'paypal_plan_id',
];
protected $casts = [
'price' => 'decimal:2',
'features' => 'array',
'limits' => 'array',
'is_active' => 'boolean',
'is_featured' => 'boolean',
'is_free' => 'boolean',
'trial_days' => 'integer',
'sort_order' => 'integer',
];
// ==================== RELATIONSHIPS ====================
public function subscriptions(): HasMany
{
return $this->hasMany(Subscription::class);
}
// ==================== SCOPES ====================
public function scopeActive($query)
{
return $query->where('is_active', true);
}
public function scopeOrdered($query)
{
return $query->orderBy('sort_order')->orderBy('price');
}
public function scopeFree($query)
{
return $query->where('billing_period', 'free');
}
public function scopePaid($query)
{
return $query->where('billing_period', '!=', 'free');
}
// ==================== ACCESSORS ====================
public function getIsFreeAttribute(): bool
{
return $this->billing_period === 'free' || $this->price == 0;
}
public function getHasTrialAttribute(): bool
{
return $this->trial_days > 0;
}
public function getFormattedPriceAttribute(): string
{
if ($this->is_free) {
return 'Gratis';
}
$symbols = [
'EUR' => '€',
'USD' => '$',
'BRL' => 'R$',
];
$symbol = $symbols[$this->currency] ?? $this->currency;
$period = match ($this->billing_period) {
'monthly' => '/mes',
'annual' => '/año',
'lifetime' => ' (único)',
default => '',
};
return $symbol . number_format($this->price, 2, ',', '.') . $period;
}
public function getMonthlyPriceAttribute(): float
{
if ($this->billing_period === 'annual') {
return round($this->price / 12, 2);
}
return $this->price;
}
public function getSavingsPercentAttribute(): ?int
{
if ($this->billing_period !== 'annual') {
return null;
}
// Find monthly equivalent
$monthlyPlan = static::where('billing_period', 'monthly')
->where('is_active', true)
->where('price', '>', 0)
->first();
if (!$monthlyPlan) {
return null;
}
$annualEquivalent = $monthlyPlan->price * 12;
$savings = (($annualEquivalent - $this->price) / $annualEquivalent) * 100;
return (int) round($savings);
}
// ==================== METHODS ====================
public function hasFeature(string $feature): bool
{
return in_array($feature, $this->features ?? []);
}
public function getLimit(string $key, $default = null)
{
return $this->limits[$key] ?? $default;
}
/**
* Get the default free plan
*/
public static function getFreePlan(): ?self
{
return static::where('slug', 'free')->first();
}
/**
* Get plans for pricing page
*/
public static function getForPricing(): \Illuminate\Database\Eloquent\Collection
{
return static::active()->ordered()->get();
}
}