billing->balanceMinor($user->public_id) / 100; } public function canCreate(User $user): bool { $priceMinor = (int) round(QrWallet::pricePerQr() * 100); return $this->billing->canAfford($user->public_id, $priceMinor); } public function debitForQrCreation(QrWallet $wallet, QrCode $qrCode): QrTransaction { $price = QrWallet::pricePerQr(); $priceMinor = (int) round($price * 100); $user = $wallet->user; $reference = 'QR-DEBIT-'.strtoupper(Str::random(12)); $result = $this->billing->debit( $user->public_id, $priceMinor, 'qr', 'qr_create', $reference, $qrCode->id, sprintf('Created QR code: %s', $qrCode->label), ); if ($result === null) { throw new RuntimeException('Insufficient wallet balance.'); } $wallet->increment('qr_codes_total'); $balanceAfter = isset($result['balance_after_minor']) ? ((int) $result['balance_after_minor']) / 100 : $this->billing->balanceMinor($user->public_id) / 100; return QrTransaction::create([ 'user_id' => $wallet->user_id, 'qr_wallet_id' => $wallet->id, 'qr_code_id' => $qrCode->id, 'type' => QrTransaction::TYPE_DEBIT, 'amount_ghs' => round($price, 4), 'balance_after_ghs' => $balanceAfter, 'reference' => $reference, 'status' => 'completed', 'description' => sprintf('Created QR code: %s', $qrCode->label), 'metadata' => ['qr_code_id' => $qrCode->id], ]); } }