diff --git a/app/Http/Controllers/Api/ShoppingUserController.php b/app/Http/Controllers/Api/ShoppingUserController.php index 0489e69..d24094f 100755 --- a/app/Http/Controllers/Api/ShoppingUserController.php +++ b/app/Http/Controllers/Api/ShoppingUserController.php @@ -710,7 +710,14 @@ class ShoppingUserController extends Controller $error[] = 'article parameter is missing'; } else { - $product = Product::whereWpNumber($order->article)->first(); + // Variations-SKUs aus dem Shop (z. B. „10042-1") sind dasselbe Produkt: + // für die Zuordnung zählt nur der Teil vor dem ersten „-". Das Original + // bleibt in $order->article, damit das API-Protokoll die echte SKU zeigt. + $baseArticle = trim(explode('-', trim((string) $order->article), 2)[0]); + + $product = $baseArticle !== '' + ? Product::whereWpNumber($baseArticle)->first() + : null; if (! $product) { $error[] = 'article not found'; } else { diff --git a/tests/Feature/ApiOrderLogTest.php b/tests/Feature/ApiOrderLogTest.php index 81aebf2..4a4c5b4 100644 --- a/tests/Feature/ApiOrderLogTest.php +++ b/tests/Feature/ApiOrderLogTest.php @@ -150,6 +150,49 @@ test('bekannte sku ohne menge wird als fehler markiert (position fehlt in der be ->and(ShoppingOrderItem::query()->where('product_id', $product->id)->count())->toBe(0); }); +test('variations-sku wird dem basisprodukt zugeordnet', function () { + // Shop-Variationen (z. B. „10042-1") sind dasselbe Produkt: für die + // Zuordnung zählt nur der Teil vor dem ersten „-". + Mail::fake(); + Passport::actingAs(apilogMakeUser()); + $product = apilogMakeProduct('Apilog Variante', 10042); + apilogMakeShoppingUser(4716); + + $this->postJson('https://api.'.config('app.api_domain').'/wp/order', [ + 'wp_order_number' => 4716, + 'wp_order' => [ + ['article' => '10042-1', 'qty' => 1, 'price' => 1990], + ], + ])->assertOk(); + + $log = ApiOrderLog::query()->sole(); + expect($log->has_errors)->toBeFalse() + ->and($log->payload['lines'][0]['article'])->toBe('10042-1') // Original-SKU bleibt im Protokoll + ->and($log->payload['lines'][0]['product_id'])->toBe($product->id) + ->and($log->payload['lines'][0]['failed'])->toBeFalse(); + + expect(ShoppingOrderItem::query()->where('shopping_order_id', $log->shopping_order_id)->where('product_id', $product->id)->count())->toBe(1); +}); + +test('sku ohne basis vor dem minus wird nicht zugeordnet', function () { + Mail::fake(); + Passport::actingAs(apilogMakeUser()); + apilogMakeProduct('Apilog NullNummer', 10043); + apilogMakeShoppingUser(4717); + + $this->postJson('https://api.'.config('app.api_domain').'/wp/order', [ + 'wp_order_number' => 4717, + 'wp_order' => [ + ['article' => '-1', 'qty' => 1, 'price' => 1990], + ], + ])->assertOk(); + + $log = ApiOrderLog::query()->sole(); + expect($log->has_errors)->toBeTrue() + ->and($log->payload['lines'][0]['failed'])->toBeTrue() + ->and($log->payload['lines'][0]['messages'])->toContain('article not found'); +}); + test('fehlerfreie uebertragung wird als ok protokolliert', function () { Mail::fake(); Passport::actingAs(apilogMakeUser());