Proof-PDF + Extra-PM-Verkauf ueber die Credit-Wallet (Decision-Update 2.1/2.3)

- ProofPdfService: Veroeffentlichungsnachweis 3 Credits pauschal, einmal pro
  PM (Zweitdownload kostenfrei); ProofPdfRenderer erzeugt das PDF on-demand
  aus vorhandenen PM-Daten (kein externer Renderer); GET-Download-Endpoint
  /admin/me/press-releases/{id}/nachweis hinter downloadProof-Policy + Kauf-Gate
- ExtraPmPurchaseService: tier-gestaffelter Nachkauf (19/15/12/10/8) aus der
  Wallet; verbucht als bezahlter SinglePurchase(ExtraPm) und greift damit in
  die bestehende Kontingent-/Slot-Mechanik. InsufficientCreditsException
  liefert das Mini-Checkout-Signal (required/available/shortfall)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-06-17 14:28:08 +00:00
parent c7a4c8bfd4
commit 69411b4c87
8 changed files with 609 additions and 0 deletions

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Controllers;
use App\Models\PressRelease;
use App\Services\Billing\ProofPdfService;
use App\Services\PressRelease\ProofPdfRenderer;
use Illuminate\Support\Facades\Gate;
use Symfony\Component\HttpFoundation\Response;
/**
* Liefert den Veröffentlichungsnachweis-PDF einer PM zum Download. Der Nachweis
* muss zuvor gekauft sein (3 Credits, einmalig pro PM – {@see ProofPdfService});
* der Kauf selbst erfolgt im Kundenbereich, nicht über diesen GET-Endpunkt.
*/
class ProofPdfController extends Controller
{
public function __invoke(
string $id,
ProofPdfService $service,
ProofPdfRenderer $renderer,
): Response {
$pressRelease = PressRelease::query()->withoutGlobalScopes()->findOrFail((int) $id);
Gate::authorize('downloadProof', $pressRelease);
abort_unless($service->hasPurchased(auth()->user(), $pressRelease), 403, 'Veröffentlichungsnachweis noch nicht gekauft.');
return $renderer->downloadResponse($pressRelease);
}
}