PM-Detailseite: Depublikations-Sektion ans Seitenende verschoben
Der seltene Ausnahme-Service stand zwischen Add-ons und Inhalt; jetzt steht er als letzte Sektion unter dem Inhalt (QA-Befund 07.07.). Dazu zwei UI-Tests: Sektion + Unternehmer-Bestätigungs-Protokoll auf der Detailseite, Ausblenden ohne Preis bzw. bei laufendem Vorgang. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9600a4f887
commit
d7f17bbc76
2 changed files with 103 additions and 55 deletions
|
|
@ -574,61 +574,6 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
|
|||
</article>
|
||||
@endif
|
||||
|
||||
{{-- ============== DEPUBLIKATION (T12, Meldeverfahren Weg 3) ============== --}}
|
||||
@if ($pr->status === PressReleaseStatus::Published && $depublicationPriceCents > 0)
|
||||
@php
|
||||
$depubNet = number_format($depublicationPriceCents / 100, 2, ',', '.');
|
||||
$depubGross = number_format($depublicationPriceCents * (1 + (float) config('billing.vat_rate')) / 100, 2, ',', '.');
|
||||
@endphp
|
||||
<article class="panel">
|
||||
<div class="panel-head">
|
||||
<span class="section-eyebrow">{{ __('Depublikation (Service)') }}</span>
|
||||
</div>
|
||||
<div class="p-5 space-y-3">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="w-9 h-9 rounded-[5px] flex items-center justify-center flex-shrink-0 bg-[color:var(--color-hub-soft)] text-[color:var(--color-hub)]">
|
||||
<flux:icon.eye-slash class="size-[18px]" />
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<h3 class="text-[14px] font-bold text-[color:var(--color-ink)] m-0">{{ __('Aus der öffentlichen Ansicht entfernen') }}</h3>
|
||||
<p class="text-[12.5px] text-[color:var(--color-ink-2)] mt-1 mb-0">
|
||||
{{ __('Freiwillige Entfernung dieser veröffentlichten Mitteilung — die öffentliche URL zeigt danach dauerhaft einen Entfernt-Hinweis. Kopien in Suchmaschinen oder Drittarchiven können zeitweise weiter verfügbar sein. Preis: :net € zzgl. USt. (:gross € inkl. 19 % USt.)', ['net' => $depubNet, 'gross' => $depubGross]) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($depublicationRequested)
|
||||
<div class="rounded-[6px] border border-[color:var(--color-ok)]/30 bg-[color:var(--color-ok-soft)] px-3 py-2 text-[12.5px] text-[color:var(--color-gain-deep)]">
|
||||
{{ __('Für diese Pressemitteilung liegt bereits ein Depublikations-Vorgang vor.') }}
|
||||
</div>
|
||||
@else
|
||||
<div class="space-y-2">
|
||||
<flux:switch
|
||||
align="left"
|
||||
wire:model.live="depublicationConfirmed"
|
||||
:label="__('Ich bestelle in Ausübung meiner gewerblichen oder selbständigen beruflichen Tätigkeit (§ 14 BGB) und akzeptiere die AGB.')"
|
||||
/>
|
||||
<p class="text-[11.5px] text-[color:var(--color-ink-3)] m-0">
|
||||
<a href="{{ route('agb', ['edition' => 'de']) }}" target="_blank" rel="noopener" class="underline underline-offset-2 hover:text-[color:var(--color-ink)]">
|
||||
{{ __('AGB (Version :version)', ['version' => \App\Models\LegalDocument::currentAgbVersion()]) }}
|
||||
</a>
|
||||
· {{ __('Gesetzliche Ansprüche (z. B. DSGVO) bleiben davon unberührt und sind immer kostenlos.') }}
|
||||
</p>
|
||||
</div>
|
||||
@if ($depublicationConfirmed)
|
||||
<flux:button size="sm" variant="primary" icon="lock-closed" href="{{ route('me.checkout.depublication', $pr->id) }}">
|
||||
{{ __('Kostenpflichtig depublizieren') }}
|
||||
</flux:button>
|
||||
@else
|
||||
<flux:button size="sm" variant="primary" icon="lock-closed" disabled>
|
||||
{{ __('Kostenpflichtig depublizieren') }}
|
||||
</flux:button>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</article>
|
||||
@endif
|
||||
|
||||
@if ($pr->status === PressReleaseStatus::Review)
|
||||
<article class="panel" style="border-color:var(--color-warn); border-left-width:3px; background:var(--color-warn-soft);">
|
||||
<div class="panel-head">
|
||||
|
|
@ -944,6 +889,63 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends
|
|||
</article>
|
||||
@endif
|
||||
|
||||
{{-- ============== DEPUBLIKATION (T12, Meldeverfahren Weg 3) ==============
|
||||
Bewusst ganz unten (QA-Befund 07.07.): seltener Ausnahme-Service,
|
||||
soll nicht zwischen Add-ons und Inhalt um Aufmerksamkeit konkurrieren. --}}
|
||||
@if ($pr->status === PressReleaseStatus::Published && $depublicationPriceCents > 0)
|
||||
@php
|
||||
$depubNet = number_format($depublicationPriceCents / 100, 2, ',', '.');
|
||||
$depubGross = number_format($depublicationPriceCents * (1 + (float) config('billing.vat_rate')) / 100, 2, ',', '.');
|
||||
@endphp
|
||||
<article class="panel">
|
||||
<div class="panel-head">
|
||||
<span class="section-eyebrow">{{ __('Depublikation (Service)') }}</span>
|
||||
</div>
|
||||
<div class="p-5 space-y-3">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="w-9 h-9 rounded-[5px] flex items-center justify-center flex-shrink-0 bg-[color:var(--color-hub-soft)] text-[color:var(--color-hub)]">
|
||||
<flux:icon.eye-slash class="size-[18px]" />
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<h3 class="text-[14px] font-bold text-[color:var(--color-ink)] m-0">{{ __('Aus der öffentlichen Ansicht entfernen') }}</h3>
|
||||
<p class="text-[12.5px] text-[color:var(--color-ink-2)] mt-1 mb-0">
|
||||
{{ __('Freiwillige Entfernung dieser veröffentlichten Mitteilung — die öffentliche URL zeigt danach dauerhaft einen Entfernt-Hinweis. Kopien in Suchmaschinen oder Drittarchiven können zeitweise weiter verfügbar sein. Preis: :net € zzgl. USt. (:gross € inkl. 19 % USt.)', ['net' => $depubNet, 'gross' => $depubGross]) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($depublicationRequested)
|
||||
<div class="rounded-[6px] border border-[color:var(--color-ok)]/30 bg-[color:var(--color-ok-soft)] px-3 py-2 text-[12.5px] text-[color:var(--color-gain-deep)]">
|
||||
{{ __('Für diese Pressemitteilung liegt bereits ein Depublikations-Vorgang vor.') }}
|
||||
</div>
|
||||
@else
|
||||
<div class="space-y-2">
|
||||
<flux:switch
|
||||
align="left"
|
||||
wire:model.live="depublicationConfirmed"
|
||||
:label="__('Ich bestelle in Ausübung meiner gewerblichen oder selbständigen beruflichen Tätigkeit (§ 14 BGB) und akzeptiere die AGB.')"
|
||||
/>
|
||||
<p class="text-[11.5px] text-[color:var(--color-ink-3)] m-0">
|
||||
<a href="{{ route('agb', ['edition' => 'de']) }}" target="_blank" rel="noopener" class="underline underline-offset-2 hover:text-[color:var(--color-ink)]">
|
||||
{{ __('AGB (Version :version)', ['version' => \App\Models\LegalDocument::currentAgbVersion()]) }}
|
||||
</a>
|
||||
· {{ __('Gesetzliche Ansprüche (z. B. DSGVO) bleiben davon unberührt und sind immer kostenlos.') }}
|
||||
</p>
|
||||
</div>
|
||||
@if ($depublicationConfirmed)
|
||||
<flux:button size="sm" variant="primary" icon="lock-closed" href="{{ route('me.checkout.depublication', $pr->id) }}">
|
||||
{{ __('Kostenpflichtig depublizieren') }}
|
||||
</flux:button>
|
||||
@else
|
||||
<flux:button size="sm" variant="primary" icon="lock-closed" disabled>
|
||||
{{ __('Kostenpflichtig depublizieren') }}
|
||||
</flux:button>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</article>
|
||||
@endif
|
||||
|
||||
{{-- ============== MODAL: NICHT GENÜGEND CREDITS ==============
|
||||
Öffnet sich serverseitig, wenn ein Add-on-Kauf (Boost/Nachweis)
|
||||
am Wallet-Guthaben scheitert — mit Direktlink zum Aufladen. --}}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use Database\Seeders\RolesAndPermissionsSeeder;
|
|||
use Illuminate\Http\RedirectResponse;
|
||||
use Laravel\Cashier\Checkout;
|
||||
use Laravel\Cashier\Events\WebhookReceived;
|
||||
use Livewire\Volt\Volt as LivewireVolt;
|
||||
use Tests\TestCase;
|
||||
|
||||
beforeEach(function (): void {
|
||||
|
|
@ -114,6 +115,51 @@ test('the depublication checkout creates a pending purchase and hands it to stri
|
|||
expect(SinglePurchase::count())->toBe(1);
|
||||
});
|
||||
|
||||
test('the detail page offers depublication and logs the entrepreneur confirmation', function () {
|
||||
/** @var TestCase $this */
|
||||
$user = depublicationCustomer();
|
||||
$release = publishedReleaseFor($user);
|
||||
BookingConfirmation::query()->delete(); // nur die Bestätigung aus dem Test-Setup entfernen
|
||||
|
||||
$this->actingAs($user);
|
||||
|
||||
LivewireVolt::test('customer.press-releases.show', ['id' => $release->id])
|
||||
->assertSee('Depublikation (Service)')
|
||||
->assertSee('Kostenpflichtig depublizieren')
|
||||
->set('depublicationConfirmed', true);
|
||||
|
||||
$confirmation = BookingConfirmation::sole();
|
||||
expect($confirmation->booking_type)->toBe('depublication');
|
||||
expect($confirmation->booking_ref)->toBe((string) $release->id);
|
||||
expect($confirmation->user_id)->toBe($user->id);
|
||||
});
|
||||
|
||||
test('the detail page hides the depublication offer without a price and after a purchase', function () {
|
||||
/** @var TestCase $this */
|
||||
$user = depublicationCustomer();
|
||||
$release = publishedReleaseFor($user);
|
||||
$this->actingAs($user);
|
||||
|
||||
// Ohne konfigurierten Preis erscheint die Sektion gar nicht (T12).
|
||||
config()->set('billing.depublication_price_cents', null);
|
||||
LivewireVolt::test('customer.press-releases.show', ['id' => $release->id])
|
||||
->assertDontSee('Depublikation (Service)');
|
||||
|
||||
// Mit laufendem Vorgang: Hinweis statt erneutem Kauf-Button.
|
||||
config()->set('billing.depublication_price_cents', 19900);
|
||||
SinglePurchase::query()->create([
|
||||
'user_id' => $user->id,
|
||||
'type' => SinglePurchaseType::Depublication->value,
|
||||
'status' => SinglePurchaseStatus::Pending->value,
|
||||
'price_cents' => 19900,
|
||||
'currency' => 'EUR',
|
||||
'press_release_id' => $release->id,
|
||||
]);
|
||||
LivewireVolt::test('customer.press-releases.show', ['id' => $release->id])
|
||||
->assertSee('Für diese Pressemitteilung liegt bereits ein Depublikations-Vorgang vor.')
|
||||
->assertDontSee('Kostenpflichtig depublizieren');
|
||||
});
|
||||
|
||||
test('the paid webhook depublishes the release and the public page shows a tombstone', function () {
|
||||
/** @var TestCase $this */
|
||||
$user = depublicationCustomer();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue