'decimal:4', 'qr_codes_total' => 'integer', 'scans_total' => 'integer', ]; public static function pricePerQr(): float { return (float) config('qr.price_per_qr_ghs', 5.0); } public static function minTopupGhs(): float { return (float) config('qr.min_topup_ghs', 5.0); } public function user(): BelongsTo { return $this->belongsTo(User::class); } public function transactions(): HasMany { return $this->hasMany(QrTransaction::class)->latest(); } /** * Single-wallet (siloing step 2): QR spends from the one UserWallet (tagged * 'qr'). Delegates to the billing service (lazily folds any legacy * credit_balance in). `spendableBalance()` is the unified balance for display. */ public function spendableBalance(): float { return $this->user ? app(\App\Services\Qr\QrWalletBillingService::class)->balanceCedis($this->user) : (float) $this->credit_balance; } public function canCreateQr(): bool { return $this->user ? app(\App\Services\Qr\QrWalletBillingService::class)->canCreate($this->user) : false; } }