Standard-Shop fuer jeden Berater: Kundenbestellung ohne Shop crashte nicht mehr
Berater ohne UserShop liefen bei Kundenbestellungen (abo-ot-customer) in "Attempt to read property id on null". Shops werden jetzt bei Freischaltung und bei Bedarf automatisch angelegt (Name aus Vor-/Nachname, bei Belegung -2, -3, ...). Nachtrag fuer Bestandsberater: php artisan user:ensure-shops. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2381bbe3b9
commit
083d643220
7 changed files with 306 additions and 7 deletions
137
tests/Feature/UserShopServiceTest.php
Normal file
137
tests/Feature/UserShopServiceTest.php
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Jeder Berater bekommt einen Standard-Shop, damit Kundenbestellungen (payment 6)
|
||||
* nicht mehr an "$user->shop->id on null" scheitern.
|
||||
*/
|
||||
|
||||
use App\Models\UserAccount;
|
||||
use App\Models\UserShop;
|
||||
use App\Services\UserShopService;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class, RefreshDatabase::class);
|
||||
|
||||
function makeShopUser(string $firstName = 'Melanie', string $lastName = 'Rauch', array $attributes = []): User
|
||||
{
|
||||
$account = UserAccount::create([
|
||||
'salutation' => 'Frau',
|
||||
'first_name' => $firstName,
|
||||
'last_name' => $lastName,
|
||||
'address' => 'Musterstr. 1',
|
||||
'zipcode' => '12345',
|
||||
'city' => 'Musterstadt',
|
||||
'phone' => '123456',
|
||||
'same_as_billing' => 1,
|
||||
'language' => 'de',
|
||||
]);
|
||||
|
||||
return User::forceCreate(array_merge([
|
||||
'email' => 'shop-'.uniqid('', true).'@example.com',
|
||||
'password' => bcrypt('secret'),
|
||||
'lang' => 'de',
|
||||
'account_id' => $account->id,
|
||||
'active' => 1,
|
||||
], $attributes));
|
||||
}
|
||||
|
||||
it('legt einen aktiven Standard-Shop aus dem Namen an', function () {
|
||||
$user = makeShopUser('Jürgen', 'Müller');
|
||||
|
||||
$shop = UserShopService::ensureForUser($user);
|
||||
|
||||
expect($shop->name)->toBe('juergen-mueller')
|
||||
->and($shop->slug)->toBe('juergen-mueller')
|
||||
->and((bool) $shop->active)->toBeTrue()
|
||||
->and($shop->active_date)->not->toBeNull()
|
||||
->and($user->shop->id)->toBe($shop->id);
|
||||
});
|
||||
|
||||
it('gibt einen vorhandenen Shop unverändert zurück', function () {
|
||||
$user = makeShopUser();
|
||||
$existing = UserShop::create(['user_id' => $user->id, 'name' => 'meinshop', 'active' => true]);
|
||||
|
||||
expect(UserShopService::ensureForUser($user)->id)->toBe($existing->id)
|
||||
->and(UserShop::where('user_id', $user->id)->count())->toBe(1);
|
||||
});
|
||||
|
||||
it('hängt bei belegtem Namen eine fortlaufende Nummer an', function () {
|
||||
$first = UserShopService::ensureForUser(makeShopUser());
|
||||
$second = UserShopService::ensureForUser(makeShopUser());
|
||||
$third = UserShopService::ensureForUser(makeShopUser());
|
||||
|
||||
expect($first->name)->toBe('melanie-rauch')
|
||||
->and($second->name)->toBe('melanie-rauch-2')
|
||||
->and($third->name)->toBe('melanie-rauch-3');
|
||||
});
|
||||
|
||||
it('kürzt lange Namen vor der Nummer an der Wortgrenze', function () {
|
||||
$other = makeShopUser('Katrin', 'Gutknecht-Stoll');
|
||||
UserShop::create(['user_id' => $other->id, 'name' => 'katrin-gutknecht', 'active' => true]);
|
||||
|
||||
$name = UserShopService::ensureForUser(makeShopUser('Katrin', 'Gutknecht-Stoll'))->name;
|
||||
|
||||
expect($name)->toBe('katrin-gutknecht-2')
|
||||
->and(strlen($name))->toBeLessThanOrEqual(20);
|
||||
});
|
||||
|
||||
it('berücksichtigt reservierte Namen im Dry-Run', function () {
|
||||
expect(UserShopService::generateDefaultName(makeShopUser(), ['melanie-rauch']))->toBe('melanie-rauch-2');
|
||||
});
|
||||
|
||||
it('berücksichtigt auch gelöschte Shops als belegt', function () {
|
||||
$other = makeShopUser();
|
||||
UserShop::create(['user_id' => $other->id, 'name' => 'melanie-rauch', 'active' => true])->delete();
|
||||
$user = makeShopUser();
|
||||
|
||||
expect(UserShopService::ensureForUser($user)->name)->toBe('melanie-rauch-2');
|
||||
});
|
||||
|
||||
it('kürzt lange Namen auf 20 Zeichen', function () {
|
||||
$user = makeShopUser('Maximiliane-Theresa', 'Schmidt-Oberhausen');
|
||||
|
||||
$name = UserShopService::ensureForUser($user)->name;
|
||||
|
||||
expect(strlen($name))->toBeLessThanOrEqual(20)
|
||||
->and($name)->toBe('maximiliane-theresa');
|
||||
});
|
||||
|
||||
it('kürzt an der Wortgrenze statt mitten im Nachnamen', function () {
|
||||
$user = makeShopUser('Theresia', 'Schifferegger');
|
||||
|
||||
expect(UserShopService::ensureForUser($user)->name)->toBe('theresia');
|
||||
});
|
||||
|
||||
it('fällt bei zu kurzem Namen auf berater zurück', function () {
|
||||
UserShopService::ensureForUser(makeShopUser('A', ''));
|
||||
|
||||
expect(UserShopService::ensureForUser(makeShopUser('B', ''))->name)->toBe('berater-2');
|
||||
});
|
||||
|
||||
it('nutzt berater ohne Account', function () {
|
||||
$user = User::forceCreate([
|
||||
'email' => 'no-account-'.uniqid('', true).'@example.com',
|
||||
'password' => bcrypt('secret'),
|
||||
'lang' => 'de',
|
||||
]);
|
||||
|
||||
expect(UserShopService::ensureForUser($user)->name)->toBe('berater');
|
||||
});
|
||||
|
||||
it('legt per Command nur für aktive Berater ohne Shop Shops an', function () {
|
||||
$withoutShop = makeShopUser('Anna', 'Beispiel');
|
||||
$withShop = makeShopUser('Bernd', 'Beispiel');
|
||||
UserShop::create(['user_id' => $withShop->id, 'name' => 'bernd-shop', 'active' => true]);
|
||||
$inactive = makeShopUser('Carla', 'Beispiel', ['active' => 0]);
|
||||
|
||||
$this->artisan('user:ensure-shops', ['--dry-run' => true])->assertSuccessful();
|
||||
expect(UserShop::count())->toBe(1);
|
||||
|
||||
$this->artisan('user:ensure-shops')->assertSuccessful();
|
||||
|
||||
expect($withoutShop->fresh()->shop->name)->toBe('anna-beispiel')
|
||||
->and($withShop->fresh()->shop->name)->toBe('bernd-shop')
|
||||
->and($inactive->fresh()->shop)->toBeNull();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue