Warenwirtschaft: AP-32-Brückenlösung — DHL-Label aus WooCommerce übernehmen
Bestell-Übertragung (wp/order) akzeptiert wp_label_url + wp_tracking_number: Label-PDF wird als lokale Kopie im privaten Storage gespeichert (Shop-URL ist öffentlich erratbar; Kopie überlebt Löschung im Shop), Sendungsnummer landet in shopping_orders.tracking. Neuer Endpoint wp/label zum Nachreichen (Connector-Hook pr_save_dhl_label_tracking), wp/status liefert die Sendungsnummer an den Shop zurück. Abwicklungs-Board + Bestell-Details zeigen Label-Download (copyreader-Dokumentroute type=label, Fallback Shop-Link) und Sendungsnummer. Download-Fehler blockieren die Übertragung nie. Doku: Connector-Update-Anleitung (dev/product management), Hinweise, Testleitfaden §11, Plan-Protokoll. pint.json schließt dev/ (Fremdcode) aus. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a1f94ea427
commit
0eed974576
13 changed files with 611 additions and 25 deletions
|
|
@ -166,9 +166,20 @@ class OrderFulfillmentController extends Controller
|
|||
*/
|
||||
public function document(int $id, string $type)
|
||||
{
|
||||
abort_unless(in_array($type, ['invoice', 'delivery', 'combined'], true), 404);
|
||||
abort_unless(in_array($type, ['invoice', 'delivery', 'combined', 'label'], true), 404);
|
||||
|
||||
$order = ShoppingOrder::query()->findOrFail($id);
|
||||
|
||||
// AP-32 Brückenlösung: lokal gespeicherte Kopie des DHL-Labels aus dem
|
||||
// WooCommerce-Shop (privater Storage — bewusst nicht die öffentliche Shop-URL)
|
||||
if ($type === 'label') {
|
||||
abort_unless($order->wp_label_path && Storage::disk('local')->exists($order->wp_label_path), 404);
|
||||
|
||||
return Response::make(Storage::disk('local')->get($order->wp_label_path), 200)
|
||||
->header('Content-Type', 'application/pdf')
|
||||
->header('Content-disposition', 'inline; filename="DHL-Label-Bestellung-'.$order->id.'.pdf"');
|
||||
}
|
||||
|
||||
abort_unless(Invoice::isInvoice($order), 404);
|
||||
|
||||
if ($type === 'combined') {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ use App\Services\Shop;
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Yard;
|
||||
|
||||
class ShoppingUserController extends Controller
|
||||
|
|
@ -64,6 +67,7 @@ class ShoppingUserController extends Controller
|
|||
'user' => $shopping_user ? true : false,
|
||||
'order' => ($shopping_user && $shopping_user->shopping_order) ? true : false,
|
||||
'status' => $shopping_user ? $shopping_user->getAPIShippedType() : false,
|
||||
'tracking_number' => ($shopping_user && $shopping_user->shopping_order) ? $shopping_user->shopping_order->tracking : null,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -364,6 +368,8 @@ class ShoppingUserController extends Controller
|
|||
}
|
||||
|
||||
$wp_invoice_path = isset($request->wp_invoice_path) ? $request->wp_invoice_path : null;
|
||||
$wp_label_url = isset($request->wp_label_url) ? $request->wp_label_url : null;
|
||||
$wp_tracking_number = isset($request->wp_tracking_number) ? $request->wp_tracking_number : null;
|
||||
$wp_advertising = isset($request->wp_advertising) ? $request->wp_advertising : '';
|
||||
$wp_incentives = isset($request->wp_incentives) ? $request->wp_incentives : '';
|
||||
|
||||
|
|
@ -375,6 +381,9 @@ class ShoppingUserController extends Controller
|
|||
$wp_order = $this->prepareOrder($wp_order, $shopping_user, $wp_invoice_path, $wp_notice);
|
||||
|
||||
if ($wp_order) {
|
||||
// AP-32 Brückenlösung: DHL-Label aus dem Shop übernehmen (Kopie lokal speichern)
|
||||
$this->storeWpLabel($shopping_user->shopping_order, $wp_label_url, $wp_tracking_number);
|
||||
|
||||
// AP-13: Übertragung inkl. SKU-Zuordnungsergebnis je Position protokollieren
|
||||
ApiOrderLog::recordTransfer($request->wp_order_number, $shopping_user, $shopping_user->shopping_order, $wp_order);
|
||||
$user = $this->prepareForShow($shopping_user);
|
||||
|
|
@ -385,6 +394,9 @@ class ShoppingUserController extends Controller
|
|||
'data' => [
|
||||
'wp_order_number' => $shopping_user->wp_order_number,
|
||||
'wp_invoice_path' => $wp_invoice_path,
|
||||
'wp_label_url' => $shopping_user->shopping_order->wp_label_url,
|
||||
'wp_label_stored' => (bool) $shopping_user->shopping_order->wp_label_path,
|
||||
'wp_tracking_number' => $shopping_user->shopping_order->tracking,
|
||||
'wp_advertising' => $wp_advertising,
|
||||
'wp_incentives' => $wp_incentives,
|
||||
'wp_order' => $wp_order,
|
||||
|
|
@ -405,6 +417,90 @@ class ShoppingUserController extends Controller
|
|||
], 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* AP-32 Brückenlösung: DHL-Label nachreichen bzw. aktualisieren — für den Fall,
|
||||
* dass das Label im Shop erst NACH der Bestell-Übertragung erstellt (oder neu
|
||||
* erstellt) wird. Der Connector kann dafür den Plugin-Hook
|
||||
* `pr_save_dhl_label_tracking` von "DHL for WooCommerce" nutzen.
|
||||
*/
|
||||
public function label(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'wp_order_number' => 'required|int',
|
||||
'wp_label_url' => 'nullable|url',
|
||||
'wp_tracking_number' => 'nullable',
|
||||
]);
|
||||
|
||||
$shopping_user = ShoppingUser::where('wp_order_number', '=', $request->wp_order_number)->first();
|
||||
if (! $shopping_user || ! $shopping_user->shopping_order) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Order with wp_order_number '.$request->wp_order_number.' not found',
|
||||
'time' => Carbon::now()->toDateTimeString(),
|
||||
], 400);
|
||||
}
|
||||
|
||||
$shopping_order = $shopping_user->shopping_order;
|
||||
$this->storeWpLabel($shopping_order, $request->wp_label_url, $request->wp_tracking_number);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'wp_order_number' => $shopping_user->wp_order_number,
|
||||
'wp_label_url' => $shopping_order->wp_label_url,
|
||||
'wp_label_stored' => (bool) $shopping_order->wp_label_path,
|
||||
'wp_tracking_number' => $shopping_order->tracking,
|
||||
],
|
||||
'time' => Carbon::now()->toDateTimeString(),
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Label-URL + Sendungsnummer aus dem WooCommerce-Shop an der Bestellung speichern.
|
||||
* Das PDF wird als lokale Kopie in den privaten Storage geladen (Auslieferung nur
|
||||
* über die Admin-Route) — so bleibt es verfügbar, auch wenn es im Shop gelöscht
|
||||
* wird, und die öffentliche Upload-URL muss nicht verlinkt werden. Ein
|
||||
* fehlgeschlagener Download darf die Übertragung nie scheitern lassen.
|
||||
*/
|
||||
private function storeWpLabel($shopping_order, $wp_label_url, $wp_tracking_number): void
|
||||
{
|
||||
if (! $shopping_order || (! $wp_label_url && ! $wp_tracking_number)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($wp_tracking_number)) {
|
||||
$wp_tracking_number = implode(', ', array_filter($wp_tracking_number));
|
||||
}
|
||||
if ($wp_tracking_number) {
|
||||
$shopping_order->tracking = $wp_tracking_number;
|
||||
}
|
||||
|
||||
if ($wp_label_url) {
|
||||
$shopping_order->wp_label_url = $wp_label_url;
|
||||
try {
|
||||
$response = Http::timeout(20)->get($wp_label_url);
|
||||
if ($response->successful() && str_starts_with($response->body(), '%PDF')) {
|
||||
$path = 'wp-labels/label-'.$shopping_order->id.'.pdf';
|
||||
Storage::disk('local')->put($path, $response->body());
|
||||
$shopping_order->wp_label_path = $path;
|
||||
} else {
|
||||
Log::warning('WP-Label-Download fehlgeschlagen (kein PDF oder HTTP-Fehler)', [
|
||||
'shopping_order_id' => $shopping_order->id,
|
||||
'wp_label_url' => $wp_label_url,
|
||||
'status' => $response->status(),
|
||||
]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('WP-Label-Download fehlgeschlagen: '.$e->getMessage(), [
|
||||
'shopping_order_id' => $shopping_order->id,
|
||||
'wp_label_url' => $wp_label_url,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$shopping_order->save();
|
||||
}
|
||||
|
||||
public function delete(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue