recordTransfer() löste die SKU erneut auf und markierte nur unbekannte Artikel als Fehler — Zeilen mit gültiger SKU aber fehlender Menge/Preis wurden verworfen und trotzdem grün protokolliert. prepareOrder() reicht jetzt included/product_id/product_name durch; failed = Position nicht übernommen. Entfernt zugleich die N+1-Produkt-Queries je Position. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
105 lines
3.9 KiB
PHP
105 lines
3.9 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
/**
|
|
* AP-13: Protokolleintrag einer Bestell-Übertragung über die Partnercenter-API (wp/order).
|
|
*
|
|
* payload['lines'] enthält je Position: article (WP-SKU), qty, price (Cent),
|
|
* product_id/product_name (Zuordnung im Partnercenter, null = nicht zugeordnet),
|
|
* messages (API-Rohmeldungen) und failed (Position wurde nicht übernommen).
|
|
*/
|
|
class ApiOrderLog extends Model
|
|
{
|
|
protected $fillable = [
|
|
'shopping_order_id',
|
|
'shopping_user_id',
|
|
'wp_order_number',
|
|
'endpoint',
|
|
'payload',
|
|
'has_errors',
|
|
'error_summary',
|
|
];
|
|
|
|
protected $casts = [
|
|
'payload' => 'array',
|
|
'has_errors' => 'bool',
|
|
];
|
|
|
|
public function shoppingOrder(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ShoppingOrder::class, 'shopping_order_id');
|
|
}
|
|
|
|
public function shoppingUser(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ShoppingUser::class, 'shopping_user_id');
|
|
}
|
|
|
|
/**
|
|
* Fehlgeschlagene Übertragung ohne verwertbare Positionen (Kunde unbekannt,
|
|
* Bestellung existiert bereits, Speicherfehler).
|
|
*
|
|
* @param mixed $rawOrder eingehender wp_order-Payload (String oder Array)
|
|
*/
|
|
public static function recordFailure(mixed $wpOrderNumber, ?ShoppingUser $shoppingUser, mixed $rawOrder, string $summary): self
|
|
{
|
|
return self::query()->create([
|
|
'shopping_user_id' => $shoppingUser?->id,
|
|
'wp_order_number' => is_numeric($wpOrderNumber) ? (int) $wpOrderNumber : null,
|
|
'endpoint' => 'order',
|
|
'payload' => ['raw' => is_string($rawOrder) ? $rawOrder : json_decode(json_encode($rawOrder), true)],
|
|
'has_errors' => true,
|
|
'error_summary' => $summary,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Erfolgreich verarbeitete Übertragung: Positionen inkl. Zuordnungsergebnis protokollieren.
|
|
* `failed` = Position wurde NICHT in die Bestellung übernommen (SKU unbekannt ODER
|
|
* Menge/Preis fehlt) — die Wahrheit kommt direkt aus prepareOrder() (`included`,
|
|
* `product_id`, `product_name`), damit Protokoll und Bestellung nie auseinanderlaufen
|
|
* (Review 20.07.2026: vorher wurde die SKU hier erneut aufgelöst, wodurch Zeilen mit
|
|
* fehlender Menge/Preis fälschlich als „OK" geloggt wurden — plus N+1-Queries).
|
|
*
|
|
* @param array<int, object> $lines Zeilen aus prepareOrder() (article/qty/price/message/included/product_id/product_name)
|
|
*/
|
|
public static function recordTransfer(mixed $wpOrderNumber, ShoppingUser $shoppingUser, ?ShoppingOrder $shoppingOrder, array $lines): self
|
|
{
|
|
$payloadLines = [];
|
|
$failedCount = 0;
|
|
|
|
foreach ($lines as $line) {
|
|
$line = (object) $line;
|
|
$failed = ! (bool) ($line->included ?? false);
|
|
if ($failed) {
|
|
$failedCount++;
|
|
}
|
|
|
|
$payloadLines[] = [
|
|
'article' => $line->article ?? null,
|
|
'qty' => $line->qty ?? null,
|
|
'price' => $line->price ?? null,
|
|
'product_id' => $line->product_id ?? null,
|
|
'product_name' => $line->product_name ?? null,
|
|
'messages' => array_values((array) ($line->message ?? [])),
|
|
'failed' => $failed,
|
|
];
|
|
}
|
|
|
|
return self::query()->create([
|
|
'shopping_order_id' => $shoppingOrder?->id,
|
|
'shopping_user_id' => $shoppingUser->id,
|
|
'wp_order_number' => is_numeric($wpOrderNumber) ? (int) $wpOrderNumber : null,
|
|
'endpoint' => 'order',
|
|
'payload' => ['lines' => $payloadLines],
|
|
'has_errors' => $failedCount > 0,
|
|
'error_summary' => $failedCount > 0
|
|
? __(':failed von :total Positionen ohne Produktzuordnung', ['failed' => $failedCount, 'total' => count($payloadLines)])
|
|
: null,
|
|
]);
|
|
}
|
|
}
|