'DE', 'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland', 'es' => 'Alemania', 'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия', ]); } function gdprConsultant(array $userAttributes = []): User { $account = UserAccount::create([ 'm_first_name' => 'Max', 'm_last_name' => 'Mustermann', 'first_name' => 'Max', 'last_name' => 'Mustermann', 'address' => 'Musterstraße 1', 'zipcode' => '12345', 'city' => 'Musterstadt', 'phone' => '123456', 'mobil' => '987654', 'tax_number' => '12/345/67890', 'tax_identification_number' => 'DE123456789', 'birthday' => '1990-05-01', 'bank_owner' => 'Max Mustermann', 'bank_iban' => 'DE02120300000000202051', 'bank_bic' => 'BYLADEM1001', 'website' => 'https://example.com', 'facebook' => 'max.mustermann', ]); $user = User::forceCreate(array_merge([ 'email' => 'gdpr-user-'.uniqid('', true).'@example.com', 'password' => Hash::make('secret'), 'lang' => 'de', 'account_id' => $account->id, 'notes' => 'Interne Notiz', ], $userAttributes)); return $user->fresh(); } it('anonymisiert alle Stammdaten eines Beraters unwiderruflich', function () { Mail::fake(); Storage::fake('user'); Storage::fake('public'); $user = gdprConsultant(); $originalEmail = $user->email; Storage::disk('user')->put('uploads/'.$user->id.'/ausweis.pdf', 'pdf-content'); $file = File::create([ 'user_id' => $user->id, 'identifier' => 'id_card', 'filename' => 'ausweis.pdf', 'dir' => 'uploads/'.$user->id.'/', 'original_name' => 'ausweis.pdf', 'ext' => 'pdf', 'mine' => 'application/pdf', 'size' => 11, ]); DB::table('user_update_emails')->insert([ 'user_id' => $user->id, 'email' => 'neue-mail@example.com', 'token' => 'token123', 'created_at' => now(), ]); $abo = UserAbo::create([ 'user_id' => $user->id, 'shopping_user_id' => 0, 'is_for' => 'me', 'email' => $originalEmail, 'payone_userid' => 123456, 'stripe_customer_id' => 'cus_123', 'stripe_payment_method_id' => 'pm_123', 'clearingtype' => 'cc', 'carddata' => ['brand' => 'visa', 'last4' => '4242'], 'active' => false, 'status' => 4, 'abo_interval' => 1, ]); $business = UserBusiness::create([ 'user_id' => $user->id, 'month' => 6, 'year' => 2026, 'email' => $originalEmail, 'first_name' => 'Max', 'last_name' => 'Mustermann', 'user_birthday' => '01.05.1990', 'user_phone' => '49 987654', 'version' => 1, ]); app(GdprDeletionService::class)->deleteUser($user, null); $user = User::withTrashed()->find($user->id); expect($user->deleted_at)->not->toBeNull(); expect($user->email)->not->toContain($originalEmail); expect($user->email)->toStartWith('delete-'); expect($user->notes)->toBeNull(); expect($user->settings)->toBeNull(); expect($user->payment_methods)->toBeNull(); $account = UserAccount::withTrashed()->find($user->account_id); expect($account->deleted_at)->not->toBeNull(); expect($account->first_name)->toBe(GdprDeletionService::ANONYMIZED_FIRSTNAME); expect($account->last_name)->toBe(GdprDeletionService::ANONYMIZED_LASTNAME); expect($account->address)->toBeNull(); expect($account->zipcode)->toBeNull(); expect($account->city)->toBeNull(); expect($account->phone)->toBeNull(); expect($account->mobil)->toBeNull(); expect($account->tax_number)->toBeNull(); expect($account->tax_identification_number)->toBeNull(); expect($account->birthday)->toBe(''); expect($account->bank_owner)->toBeNull(); expect($account->bank_iban)->toBeNull(); expect($account->bank_bic)->toBeNull(); expect($account->website)->toBeNull(); expect($account->facebook)->toBeNull(); expect(File::find($file->id))->toBeNull(); Storage::disk('user')->assertMissing('uploads/'.$user->id.'/ausweis.pdf'); expect(UserUpdateEmail::where('user_id', $user->id)->count())->toBe(0); $abo = UserAbo::withTrashed()->find($abo->id); expect($abo->email)->toBeNull(); expect($abo->carddata)->toBeNull(); expect((int) $abo->payone_userid)->toBe(0); expect($abo->stripe_customer_id)->toBeNull(); expect($abo->stripe_payment_method_id)->toBeNull(); $business = UserBusiness::find($business->id); expect($business->email)->toBeNull(); expect($business->first_name)->toBe(GdprDeletionService::ANONYMIZED_FIRSTNAME); expect($business->user_birthday)->toBeNull(); expect($business->user_phone)->toBeNull(); }); it('hängt Downline und Kunden auf den nächsten aktiven Sponsor um', function () { Mail::fake(); Storage::fake('user'); Storage::fake('public'); $sponsor = gdprConsultant(['payment_account' => now()->addYear()]); $user = gdprConsultant(['m_sponsor' => $sponsor->id]); $child = gdprConsultant(['m_sponsor' => $user->id]); $customer = ShoppingUser::create([ 'auth_user_id' => 0, 'member_id' => $user->id, 'billing_email' => 'kunde-'.uniqid('', true).'@example.com', 'billing_country_id' => gdprCountry()->id, 'shipping_country_id' => 1, ]); app(GdprDeletionService::class)->deleteUser($user, null); expect($child->fresh()->m_sponsor)->toBe($sponsor->id); expect($customer->fresh()->member_id)->toBe($sponsor->id); }); it('blockiert die Löschung bei aktivem Abo', function () { Mail::fake(); $user = gdprConsultant(); UserAbo::create([ 'user_id' => $user->id, 'shopping_user_id' => 0, 'is_for' => 'me', 'email' => $user->email, 'payone_userid' => 111, 'clearingtype' => 'cc', 'active' => true, 'status' => 2, 'abo_interval' => 1, ]); app(GdprDeletionService::class)->deleteUser($user, null); })->throws(GdprDeletionException::class); it('blockiert die Löschung von Admin-Accounts', function () { Mail::fake(); $user = gdprConsultant(['admin' => 2]); app(GdprDeletionService::class)->deleteUser($user, null); })->throws(GdprDeletionException::class); it('anonymisiert einen Endkunden ohne Bestellungen vollständig, inkl. aller Einträge derselben Kundennummer', function () { Mail::fake(); $country = gdprCountry(); $rowOne = ShoppingUser::create([ 'auth_user_id' => 0, 'number' => 4711, 'billing_salutation' => 'Frau', 'billing_firstname' => 'Erika', 'billing_lastname' => 'Musterfrau', 'billing_address' => 'Beispielweg 2', 'billing_zipcode' => '54321', 'billing_city' => 'Beispielstadt', 'billing_phone' => '0123', 'billing_email' => 'erika@example.com', 'billing_country_id' => $country->id, 'shipping_country_id' => $country->id, 'remarks' => 'Bitte klingeln', 'subscribed' => true, ]); $rowTwo = ShoppingUser::create([ 'auth_user_id' => 0, 'number' => 4711, 'billing_firstname' => 'Erika', 'billing_lastname' => 'Musterfrau', 'billing_email' => 'erika@example.com', 'billing_country_id' => $country->id, 'shipping_country_id' => $country->id, ]); app(GdprDeletionService::class)->deleteShoppingUser($rowOne, null); foreach ([$rowOne, $rowTwo] as $row) { $row = $row->fresh(); expect($row->billing_firstname)->toBe(GdprDeletionService::ANONYMIZED_FIRSTNAME); expect($row->billing_lastname)->toBe(GdprDeletionService::ANONYMIZED_LASTNAME); expect($row->billing_address)->toBeNull(); expect($row->billing_zipcode)->toBeNull(); expect($row->billing_city)->toBeNull(); expect($row->billing_phone)->toBeNull(); expect($row->billing_email)->not->toContain('erika@example.com'); expect($row->remarks)->toBe(''); expect($row->subscribed)->toBeFalse(); expect($row->faker_mail)->toBeTrue(); } }); it('behält bei Endkunden mit Bestellung Name und Rechnungsadresse, entfernt aber alle Kontaktdaten', function () { Mail::fake(); $country = gdprCountry(); $shopOwner = User::forceCreate([ 'email' => 'shop-owner-'.uniqid('', true).'@example.com', 'password' => Hash::make('secret'), 'lang' => 'de', ]); $userShop = UserShop::create([ 'user_id' => $shopOwner->id, 'name' => 'TS'.substr(uniqid('', true), 0, 8), 'slug' => 'ts-'.uniqid(), 'active' => true, ]); $customer = ShoppingUser::create([ 'auth_user_id' => 0, 'number' => 4712, 'billing_firstname' => 'Erika', 'billing_lastname' => 'Musterfrau', 'billing_address' => 'Beispielweg 2', 'billing_zipcode' => '54321', 'billing_city' => 'Beispielstadt', 'billing_phone' => '0123', 'billing_email' => 'erika@example.com', 'billing_country_id' => $country->id, 'shipping_country_id' => $country->id, 'remarks' => 'Bitte klingeln', 'subscribed' => true, ]); ShoppingOrder::create([ 'shopping_user_id' => $customer->id, 'auth_user_id' => 0, 'country_id' => $country->id, 'user_shop_id' => $userShop->id, 'payment_for' => 6, 'total' => 100, 'subtotal' => 90, ]); app(GdprDeletionService::class)->deleteShoppingUser($customer, null); $customer = $customer->fresh(); expect($customer->billing_firstname)->toBe('Erika'); expect($customer->billing_lastname)->toBe('Musterfrau'); expect($customer->billing_address)->toBe('Beispielweg 2'); expect($customer->billing_city)->toBe('Beispielstadt'); expect($customer->billing_phone)->toBeNull(); expect($customer->billing_email)->not->toContain('erika@example.com'); expect($customer->remarks)->toBe(''); expect($customer->subscribed)->toBeFalse(); expect($customer->faker_mail)->toBeTrue(); }); it('lehnt die Endkunden-Löschung für Berater-Datensätze ab', function () { Mail::fake(); $user = gdprConsultant(); $customer = ShoppingUser::create([ 'auth_user_id' => $user->id, 'billing_email' => $user->email, 'billing_country_id' => gdprCountry()->id, 'shipping_country_id' => 1, ]); app(GdprDeletionService::class)->deleteShoppingUser($customer, null); })->throws(GdprDeletionException::class); it('entfernt Zahlungs-Tokens der Abos eines Endkunden', function () { Mail::fake(); $country = gdprCountry(); $customer = ShoppingUser::create([ 'auth_user_id' => 0, 'number' => 4713, 'billing_firstname' => 'Erika', 'billing_lastname' => 'Musterfrau', 'billing_email' => 'erika-abo@example.com', 'billing_country_id' => $country->id, 'shipping_country_id' => $country->id, ]); $abo = UserAbo::create([ 'shopping_user_id' => $customer->id, 'is_for' => 'ot', 'email' => 'erika-abo@example.com', 'payone_userid' => 999, 'clearingtype' => 'cc', 'carddata' => ['brand' => 'visa', 'last4' => '4242'], 'active' => false, 'status' => 6, 'abo_interval' => 1, ]); app(GdprDeletionService::class)->deleteShoppingUser($customer, null); $abo = UserAbo::withTrashed()->find($abo->id); expect($abo->email)->toBeNull(); expect($abo->carddata)->toBeNull(); expect((int) $abo->payone_userid)->toBe(0); }); it('löscht die Stripe-Customer-Objekte des Endkunden (SE1.6)', function () { Mail::fake(); $country = gdprCountry(); $customer = ShoppingUser::create([ 'auth_user_id' => 0, 'number' => 4714, 'billing_firstname' => 'Erika', 'billing_lastname' => 'Musterfrau', 'billing_email' => 'erika-stripe@example.com', 'billing_country_id' => $country->id, 'shipping_country_id' => $country->id, 'stripe_customer_id' => 'cus_shop_1', ]); UserAbo::create([ 'shopping_user_id' => $customer->id, 'is_for' => 'ot', 'email' => 'erika-stripe@example.com', 'payone_userid' => 0, 'payment_provider' => 'stripe', 'stripe_customer_id' => 'cus_abo_1', 'stripe_payment_method_id' => 'pm_abo_1', 'clearingtype' => 'stripe', 'active' => false, 'status' => 6, 'abo_interval' => 1, ]); $deleted = []; $stripeCustomers = Mockery::mock(StripeCustomerService::class); $stripeCustomers->shouldReceive('deleteCustomer') ->twice() ->andReturnUsing(function (string $customerId) use (&$deleted): bool { $deleted[] = $customerId; return true; }); app()->instance(StripeCustomerService::class, $stripeCustomers); $summary = app(GdprDeletionService::class)->deleteShoppingUser($customer, null); sort($deleted); expect($deleted)->toBe(['cus_abo_1', 'cus_shop_1']) ->and($summary['stripe_customers_deleted'])->toBe(2) ->and($customer->fresh()->stripe_customer_id)->toBeNull(); });