Warenwirtschaft: AP-34 — Varianten-Artikelnummer korrekt zuordnen

Bestellungen mit Produktvarianten (z. B. Deocreme MINI) wurden im Versand nicht
automatisch zugeordnet und mussten manuell nachgepflegt werden. Zwei
zusammenwirkende Fehler:

1. Connector (partnercenter-api v1.6.0): compose_cart_content() las per
   get_product_id() das Elternprodukt und sendete dessen SKU — nie die eigene
   Artikel-Nr. der Variation. Jetzt liest get_product() (variations-aware) die
   Variations-SKU, Fallback auf Eltern-SKU nur wenn leer. Plugin muss neu in den
   Shop ausgerollt werden.

2. Importer (ShoppingUserController::prepareOrder): matchte nur den Teil vor dem
   ersten „-" gegen wp_number. In der Live-DB ist jede Variante eine eigene
   products-Zeile mit eigener wp_number (kein main_product_id, keine „-"-Suffixe).
   Jetzt Zuordnung primär über die VOLLE SKU gegen wp_number; der „-"-Split bleibt
   nur Legacy-Fallback für alte Variations-SKUs „basisnr-suffix".

Tests: neue AP-34-Prüfung (MINI 100026 landet beim MINI-Produkt, nicht beim
50-ml-Basisprodukt 100006) + Legacy-Fallback-Test. Suite 327 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-08-28 09:32:51 +00:00
parent 190713c21b
commit 8c938eed0a
4 changed files with 65 additions and 14 deletions

View file

@ -150,9 +150,37 @@ 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 „-".
test('AP-34: jede variante wird über ihre eigene volle SKU dem richtigen produkt zugeordnet', function () {
// Ab Connector v1.6 sendet der Shop die Variations-Artikel-Nr. selbst. In der DB
// ist jede Variante eine eigene products-Zeile mit eigener wp_number (kein
// main_product_id, kein „-"-Suffix). Eine Bestellung der MINI-Variante (100026)
// darf NICHT beim 50-ml-Basisprodukt (100006) landen.
Mail::fake();
Passport::actingAs(apilogMakeUser());
$parent = apilogMakeProduct('Deocreme Angekommen 50 ml', 100006);
$mini = apilogMakeProduct('Deocreme Angekommen MINI 5 ml', 100026);
apilogMakeShoppingUser(4730);
$this->postJson('https://api.'.config('app.api_domain').'/wp/order', [
'wp_order_number' => 4730,
'wp_order' => [
['article' => 100026, 'qty' => 1, 'price' => 1990],
],
])->assertOk();
$log = ApiOrderLog::query()->sole();
expect($log->has_errors)->toBeFalse()
->and($log->payload['lines'][0]['product_id'])->toBe($mini->id)
->and($log->payload['lines'][0]['product_id'])->not->toBe($parent->id)
->and($log->payload['lines'][0]['failed'])->toBeFalse();
expect(ShoppingOrderItem::query()->where('shopping_order_id', $log->shopping_order_id)->where('product_id', $mini->id)->count())->toBe(1)
->and(ShoppingOrderItem::query()->where('shopping_order_id', $log->shopping_order_id)->where('product_id', $parent->id)->count())->toBe(0);
});
test('variations-sku im legacy-format „basisnr-suffix" wird als fallback zugeordnet', function () {
// Rückwärtskompatibilität: sollte der Shop noch eine alte Variations-SKU im
// Format „10042-1" senden, greift der „-"-Split-Fallback auf die Basisnummer.
Mail::fake();
Passport::actingAs(apilogMakeUser());
$product = apilogMakeProduct('Apilog Variante', 10042);