Widerruf: Gesetzliche Online-Widerrufsfunktion (Formular, Bestätigungsmail, Admin-Verwaltung)

- Öffentliches Widerrufsformular /widerruf mit Bestell-Lookup (throttled)
- Bestätigungsmail an Kunde + Weiterleitung an bestellungen@ (config app.withdrawal_mail)
- Admin-Übersicht/-Detail unter /admin/withdrawals inkl. Sidenav-Eintrag
- Widerruf-Button in Portal-Bestellansicht und Footer-Links
- Model OrderWithdrawal + Migration + Factory + Tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-07-08 15:56:02 +00:00
parent eac923968d
commit 63c36555a5
24 changed files with 1607 additions and 92 deletions

View file

@ -1,5 +1,80 @@
<?php
use Acme\Dhl\DhlServiceProvider;
use Acme\Dhl\Facades\DHL;
use Alban\LaravelCollectiveSpatieHtmlParser\FormFacade;
use Alban\LaravelCollectiveSpatieHtmlParser\HtmlFacade;
use Alban\LaravelCollectiveSpatieHtmlParser\ServiceProvider;
use App\Providers\AppServiceProvider;
use App\Providers\EventServiceProvider;
use App\Providers\HorizonServiceProvider;
use App\Providers\RouteServiceProvider;
use App\Providers\YardServiceProvider;
use App\Services\Facade\Yard;
use App\Services\HTMLHelper;
use App\Services\Util;
use Illuminate\Auth\AuthServiceProvider;
use Illuminate\Auth\Passwords\PasswordResetServiceProvider;
use Illuminate\Broadcasting\BroadcastServiceProvider;
use Illuminate\Bus\BusServiceProvider;
use Illuminate\Cache\CacheServiceProvider;
use Illuminate\Cookie\CookieServiceProvider;
use Illuminate\Database\DatabaseServiceProvider;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Encryption\EncryptionServiceProvider;
use Illuminate\Filesystem\FilesystemServiceProvider;
use Illuminate\Foundation\Providers\ConsoleSupportServiceProvider;
use Illuminate\Foundation\Providers\FoundationServiceProvider;
use Illuminate\Hashing\HashServiceProvider;
use Illuminate\Mail\MailServiceProvider;
use Illuminate\Notifications\NotificationServiceProvider;
use Illuminate\Pagination\PaginationServiceProvider;
use Illuminate\Pipeline\PipelineServiceProvider;
use Illuminate\Queue\QueueServiceProvider;
use Illuminate\Redis\RedisServiceProvider;
use Illuminate\Session\SessionServiceProvider;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\View;
use Illuminate\Translation\TranslationServiceProvider;
use Illuminate\Validation\ValidationServiceProvider;
use Illuminate\View\ViewServiceProvider;
use Jenssegers\Date\Date;
use Jenssegers\Date\DateServiceProvider;
use Laravel\Tinker\TinkerServiceProvider;
use Maatwebsite\Excel\ExcelServiceProvider;
use Maatwebsite\Excel\Facades\Excel;
use Yajra\DataTables\DataTablesServiceProvider;
use Yajra\DataTables\Facades\DataTables;
return [
/*
@ -64,6 +139,7 @@ return [
'checkout_url' => env('APP_URL_CHECKOUT', 'checkout.'),
'contact_mail' => env('APP_CONTACT_MAIL', 'kontakt@mivita.care'),
'withdrawal_mail' => env('APP_WITHDRAWAL_MAIL', 'bestellungen@mivita.care'),
'checkout_mail' => env('APP_CHECKOUT_MAIL', 'no-reply@mivita.care'),
'checkout_test_mail' => env('APP_CHECKOUT_TEST_MAIL', 'devtest@mivita.care'),
'info_mail' => env('APP_INFO_MAIL', 'no-reply@mivita.care'),
@ -74,7 +150,6 @@ return [
'ipinfo' => env('APP_IPINFO', false),
'main_tax' => env('APP_MAIN_TAX', 1.19),
'main_tax_rate' => env('APP_MAIN_TAX_RATE', 19),
'shipping_tax' => env('APP_SHIPPING_TAX', 19),
@ -86,7 +161,6 @@ return [
'url_backend' => env('APP_URL', 'http://mivita.local/'),
*/
/*
|--------------------------------------------------------------------------
| Application Timezone
@ -157,53 +231,53 @@ return [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
//Reliese\Coders\CodersServiceProvider::class,
//Intervention\Image\ImageServiceProvider::class,
AuthServiceProvider::class,
BroadcastServiceProvider::class,
BusServiceProvider::class,
CacheServiceProvider::class,
ConsoleSupportServiceProvider::class,
CookieServiceProvider::class,
DatabaseServiceProvider::class,
EncryptionServiceProvider::class,
FilesystemServiceProvider::class,
FoundationServiceProvider::class,
HashServiceProvider::class,
MailServiceProvider::class,
NotificationServiceProvider::class,
PaginationServiceProvider::class,
PipelineServiceProvider::class,
QueueServiceProvider::class,
RedisServiceProvider::class,
PasswordResetServiceProvider::class,
SessionServiceProvider::class,
TranslationServiceProvider::class,
ValidationServiceProvider::class,
ViewServiceProvider::class,
// Reliese\Coders\CodersServiceProvider::class,
// Intervention\Image\ImageServiceProvider::class,
/*
* Package Service Providers...
*/
Laravel\Tinker\TinkerServiceProvider::class,
TinkerServiceProvider::class,
/*
* DHL Package Service Provider...
*/
Acme\Dhl\DhlServiceProvider::class,
DhlServiceProvider::class,
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\HorizonServiceProvider::class,
//App\Providers\DomainServiceProvider::class,
App\Providers\RouteServiceProvider::class,
Jenssegers\Date\DateServiceProvider::class,
Maatwebsite\Excel\ExcelServiceProvider::class,
Yajra\DataTables\DataTablesServiceProvider::class,
App\Providers\YardServiceProvider::class,
Alban\LaravelCollectiveSpatieHtmlParser\ServiceProvider::class,
EventServiceProvider::class,
HorizonServiceProvider::class,
// App\Providers\DomainServiceProvider::class,
RouteServiceProvider::class,
DateServiceProvider::class,
ExcelServiceProvider::class,
DataTablesServiceProvider::class,
YardServiceProvider::class,
ServiceProvider::class,
],
/*
@ -220,50 +294,50 @@ return [
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class,
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
'Bus' => Illuminate\Support\Facades\Bus::class,
'Cache' => Illuminate\Support\Facades\Cache::class,
'Config' => Illuminate\Support\Facades\Config::class,
'Cookie' => Illuminate\Support\Facades\Cookie::class,
'Crypt' => Illuminate\Support\Facades\Crypt::class,
'DB' => Illuminate\Support\Facades\DB::class,
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
'Event' => Illuminate\Support\Facades\Event::class,
'File' => Illuminate\Support\Facades\File::class,
'Gate' => Illuminate\Support\Facades\Gate::class,
'Hash' => Illuminate\Support\Facades\Hash::class,
'Lang' => Illuminate\Support\Facades\Lang::class,
'Log' => Illuminate\Support\Facades\Log::class,
'Mail' => Illuminate\Support\Facades\Mail::class,
'Notification' => Illuminate\Support\Facades\Notification::class,
'Password' => Illuminate\Support\Facades\Password::class,
'Queue' => Illuminate\Support\Facades\Queue::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
'Redis' => Illuminate\Support\Facades\Redis::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class,
'Route' => Illuminate\Support\Facades\Route::class,
'Schema' => Illuminate\Support\Facades\Schema::class,
'Session' => Illuminate\Support\Facades\Session::class,
'Storage' => Illuminate\Support\Facades\Storage::class,
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
//'Input' => Illuminate\Support\Facades\Input::class,
//'Image' => Intervention\Image\Facades\Image::class,
'Carbon' => Carbon\Carbon::class,
'Date' => Jenssegers\Date\Date::class,
'HTMLHelper' => App\Services\HTMLHelper::class,
'Util' => App\Services\Util::class,
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
'DataTables' => Yajra\DataTables\Facades\DataTables::class,
'Yard' => App\Services\Facade\Yard::class,
'DHL' => Acme\Dhl\Facades\DHL::class,
'Form' => Alban\LaravelCollectiveSpatieHtmlParser\FormFacade::class,
'Html' => Alban\LaravelCollectiveSpatieHtmlParser\HtmlFacade::class,
'Artisan' => Artisan::class,
'Auth' => Auth::class,
'Blade' => Blade::class,
'Broadcast' => Broadcast::class,
'Bus' => Bus::class,
'Cache' => Cache::class,
'Config' => Config::class,
'Cookie' => Cookie::class,
'Crypt' => Crypt::class,
'DB' => DB::class,
'Eloquent' => Model::class,
'Event' => Event::class,
'File' => File::class,
'Gate' => Gate::class,
'Hash' => Hash::class,
'Lang' => Lang::class,
'Log' => Log::class,
'Mail' => Mail::class,
'Notification' => Notification::class,
'Password' => Password::class,
'Queue' => Queue::class,
'Redirect' => Redirect::class,
'Redis' => Redis::class,
'Request' => Request::class,
'Response' => Response::class,
'Route' => Route::class,
'Schema' => Schema::class,
'Session' => Session::class,
'Storage' => Storage::class,
'URL' => URL::class,
'Validator' => Validator::class,
'View' => View::class,
// 'Input' => Illuminate\Support\Facades\Input::class,
// 'Image' => Intervention\Image\Facades\Image::class,
'Carbon' => Carbon\Carbon::class,
'Date' => Date::class,
'HTMLHelper' => HTMLHelper::class,
'Util' => Util::class,
'Excel' => Excel::class,
'DataTables' => DataTables::class,
'Yard' => Yard::class,
'DHL' => DHL::class,
'Form' => FormFacade::class,
'Html' => HtmlFacade::class,
],
];