Files
isaaccladandCursor b6c8ac343f Extract Ladill Servers as standalone app at servers.ladill.com.
VPS and dedicated server ordering, managed panels, SSO, billing, and launcher integration — forked from hosting infrastructure with server-focused routes and dashboard.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 19:18:30 +00:00

231 lines
6.2 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
/**
* Domain pricing overrides.
*
* When a TLD has an entry here with is_override=true, the manually set GHS price
* will be used instead of the live-converted Dynadot price.
*
* Prices are stored in pesewas (minor units).
*/
class DomainPricing extends Model
{
/**
* @var array<string, bool>
*/
private static array $columnExists = [];
protected $fillable = [
'tld',
'register_price',
'renew_price',
'transfer_price',
'currency',
'is_override',
'is_featured',
'is_active',
'sort_order',
];
protected $casts = [
'register_price' => 'integer',
'renew_price' => 'integer',
'transfer_price' => 'integer',
'is_override' => 'boolean',
'is_featured' => 'boolean',
'is_active' => 'boolean',
'sort_order' => 'integer',
];
/**
* Get active pricing override for a TLD.
*/
public static function forTld(string $tld): ?self
{
$tld = ltrim(strtolower(trim($tld)), '.');
return Cache::remember(
"domain_pricing:{$tld}",
now()->addHours(1),
function () use ($tld) {
$query = static::where('tld', $tld);
if (static::hasColumn('is_active')) {
$query->where('is_active', true);
}
return $query->first();
}
);
}
/**
* Get all active price overrides.
*
* @return array<string, array{register: int, renew: int, transfer: int, is_override: bool}>
*/
public static function getOverrides(): array
{
return Cache::remember(
'domain_pricing:overrides',
now()->addHours(1),
function () {
$query = static::query();
if (static::hasColumn('is_active')) {
$query->where('is_active', true);
}
// Older installs may have used this table only for manual overrides.
if (static::hasColumn('is_override')) {
$query->where('is_override', true);
}
return $query->get()
->keyBy('tld')
->map(fn ($p) => [
'register' => $p->register_price,
'renew' => $p->renew_price,
'transfer' => $p->transfer_price,
'is_override' => static::hasColumn('is_override') ? (bool) $p->is_override : true,
])
->all();
}
);
}
/**
* Get all active TLDs with pricing.
*/
public static function activeTlds(): array
{
return Cache::remember(
'domain_pricing:active_tlds',
now()->addHours(1),
function () {
$query = static::query();
if (static::hasColumn('is_active')) {
$query->where('is_active', true);
}
if (static::hasColumn('sort_order')) {
$query->orderBy('sort_order');
}
return $query->orderBy('tld')->pluck('tld')->all();
}
);
}
/**
* Get featured TLDs for search.
*/
public static function featuredTlds(): array
{
return Cache::remember(
'domain_pricing:featured_tlds',
now()->addHours(1),
function () {
$query = static::query();
if (static::hasColumn('is_active')) {
$query->where('is_active', true);
}
if (static::hasColumn('is_featured')) {
$query->where('is_featured', true);
}
if (static::hasColumn('sort_order')) {
$query->orderBy('sort_order');
}
$tlds = $query->orderBy('tld')->pluck('tld')->all();
return $tlds !== [] ? $tlds : static::activeTlds();
}
);
}
/**
* Get pricing map for multiple TLDs.
*
* @return array<string, array{register: int, renew: int, transfer: int, currency: string}>
*/
public static function pricingMap(array $tlds = []): array
{
$query = static::query();
if (static::hasColumn('is_active')) {
$query->where('is_active', true);
}
if (! empty($tlds)) {
$query->whereIn('tld', array_map(fn ($t) => ltrim(strtolower($t), '.'), $tlds));
}
return $query->get()->keyBy('tld')->map(fn ($p) => [
'register' => $p->register_price,
'renew' => $p->renew_price,
'transfer' => $p->transfer_price,
'currency' => $p->currency,
])->all();
}
/**
* Clear pricing cache.
*/
public static function clearCache(): void
{
Cache::forget('domain_pricing:active_tlds');
Cache::forget('domain_pricing:featured_tlds');
Cache::forget('domain_pricing:overrides');
foreach (static::pluck('tld') as $tld) {
Cache::forget("domain_pricing:{$tld}");
}
}
/**
* Format price for display.
*/
public function formatRegisterPrice(): string
{
return $this->formatPrice($this->register_price);
}
public function formatRenewPrice(): string
{
return $this->formatPrice($this->renew_price);
}
public function formatTransferPrice(): string
{
return $this->formatPrice($this->transfer_price);
}
private function formatPrice(int $amountMinor): string
{
$symbol = $this->currency === 'GHS' ? 'GH₵' : $this->currency;
return $symbol . ' ' . number_format($amountMinor / 100, 2);
}
private static function hasColumn(string $column): bool
{
$cacheKey = static::class . ':' . $column;
if (! array_key_exists($cacheKey, self::$columnExists)) {
self::$columnExists[$cacheKey] = Schema::hasColumn((new static)->getTable(), $column);
}
return self::$columnExists[$cacheKey];
}
}