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)); return DB::transaction(function () use ($wallet, $user, $qrCode, $price, $priceMinor, $reference) { $ok = $this->billing->debit( $user->public_id, $priceMinor, 'qr', 'qr_create', $reference, $qrCode->id, sprintf('Created QR code: %s', $qrCode->label), ); if (! $ok) { throw new RuntimeException('Insufficient wallet balance.'); } $wallet->increment('qr_codes_total'); $balanceAfter = $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], ]); }); } }