pricing->proofPdfCredits(); } /** * Ein Nachweis ist nur für veröffentlichte Meldungen sinnvoll. */ public function isAvailable(PressRelease $pressRelease): bool { return $pressRelease->status === PressReleaseStatus::Published; } public function hasPurchased(User $user, PressRelease $pressRelease): bool { return $this->purchaseQuery($user, $pressRelease)->exists(); } /** * Kauft (oder liefert den bereits gekauften) Nachweis. Belastet die Wallet * nur beim Erstkauf. Wirft ProofPdfNotAvailableException, wenn die PM nicht * veröffentlicht ist, und InsufficientCreditsException ohne Deckung. */ public function purchase(User $user, PressRelease $pressRelease): SinglePurchase { if (! $this->isAvailable($pressRelease)) { throw ProofPdfNotAvailableException::notPublished(); } $existing = $this->purchaseQuery($user, $pressRelease)->first(); if ($existing) { return $existing; } $credits = $this->priceCredits(); return DB::transaction(function () use ($user, $pressRelease, $credits): SinglePurchase { $purchase = $user->singlePurchases()->create([ 'type' => SinglePurchaseType::ProofPdf, 'status' => SinglePurchaseStatus::Paid, 'price_cents' => $credits * 100, 'currency' => config('billing.default_currency'), 'press_release_id' => $pressRelease->id, 'paid_at' => now(), ]); $this->wallet->debit( $user, $credits, "Veröffentlichungsnachweis – PM #{$pressRelease->id}", $purchase, ); return $purchase; }); } private function purchaseQuery(User $user, PressRelease $pressRelease) { return $user->singlePurchases() ->where('type', SinglePurchaseType::ProofPdf->value) ->where('status', SinglePurchaseStatus::Paid->value) ->where('press_release_id', $pressRelease->id); } }