diff --git a/modules/erp/import-integration/service.php b/modules/erp/import-integration/service.php index 49d13fe..991f40f 100644 --- a/modules/erp/import-integration/service.php +++ b/modules/erp/import-integration/service.php @@ -135,6 +135,103 @@ function trigger_shipping_label_flow(array $order, array $localEnv): array ]; } +function trigger_excel_webhook(string $externalRef, array $localEnv): array +{ + $url = derive_excel_webhook_url($localEnv); + if ($url === '') { + return ['enabled' => false, 'ok' => false, 'message' => 'Excel webhook URL not configured']; + } + + throttle_webhook_channel('excel', 5); + $result = post_json($url, ['Bestellnummer' => $externalRef], build_n8n_webhook_headers($localEnv), 20); + + return [ + 'enabled' => true, + 'ok' => $result['ok'], + 'status' => $result['status'], + 'url' => $url, + 'message' => $result['ok'] ? 'Excel webhook triggered' : ($result['error'] !== '' ? $result['error'] : 'Excel webhook returned non-2xx'), + 'responseBody' => $result['body'], + ]; +} + +function build_legacy_label_order_payload(PDO $pdo, int $orderId): array +{ + $orderStmt = $pdo->prepare( + 'SELECT so.*, p.email, + pm.code AS payment_method_code, + sm.code AS shipping_method_code + FROM sales_order so + JOIN party p ON p.id = so.party_id + LEFT JOIN payment_method pm ON pm.id = so.payment_method_id + LEFT JOIN shipping_method sm ON sm.id = so.shipping_method_id + WHERE so.id = :order_id' + ); + $orderStmt->execute([':order_id' => $orderId]); + $order = $orderStmt->fetch(PDO::FETCH_ASSOC); + if (!is_array($order)) { + throw new RuntimeException("ERP-Bestellung {$orderId} fehlt fuer Label-Webhook"); + } + + $addressStmt = $pdo->prepare( + 'SELECT DISTINCT ON (type) type, first_name, last_name, street, house_number, + zip, city, state_code, country_name + FROM address + WHERE party_id = :party_id + ORDER BY type, id DESC' + ); + $addressStmt->execute([':party_id' => (int) $order['party_id']]); + $addresses = []; + foreach ($addressStmt->fetchAll(PDO::FETCH_ASSOC) as $address) { + $addresses[(string) $address['type']] = $address; + } + + $lineStmt = $pdo->prepare( + 'SELECT raw_external_article_number, raw_external_title, qty, unit_price + FROM sales_order_line + WHERE sales_order_id = :order_id + ORDER BY line_no, id' + ); + $lineStmt->execute([':order_id' => $orderId]); + $lineItems = []; + foreach ($lineStmt->fetchAll(PDO::FETCH_ASSOC) as $line) { + $lineItems[] = [ + 'artikelnummer' => (string) ($line['raw_external_article_number'] ?? ''), + 'titel' => (string) ($line['raw_external_title'] ?? ''), + 'artikelanzahl' => (float) $line['qty'], + 'preisEinheit' => $line['unit_price'] === null ? null : (float) $line['unit_price'], + ]; + } + + $address = static function (array $value, string $suffix): array { + return [ + "Vorname_{$suffix}" => (string) ($value['first_name'] ?? ''), + "Nachname_{$suffix}" => (string) ($value['last_name'] ?? ''), + "Strasse_{$suffix}" => (string) ($value['street'] ?? ''), + "Hausnummer_{$suffix}" => (string) ($value['house_number'] ?? ''), + "PLZ_{$suffix}" => (string) ($value['zip'] ?? ''), + "Stadt_{$suffix}" => (string) ($value['city'] ?? ''), + "Bundesland_{$suffix}" => (string) ($value['state_code'] ?? ''), + "Land_{$suffix}" => (string) ($value['country_name'] ?? ''), + ]; + }; + + return array_merge([ + 'BestellungNr' => (string) $order['external_ref'], + 'EmailKunde' => (string) ($order['email'] ?? ''), + 'Bestelldatum' => (new DateTimeImmutable((string) $order['order_date']))->format('Y-m-d\\TH:i:s'), + 'Zahlungsmethode' => (string) ($order['payment_method_code'] ?? ''), + 'Zahlungsstatus' => (string) $order['payment_status'], + 'Liefermethode' => (string) ($order['shipping_method_code'] ?? ''), + 'Netto' => (float) ($order['amount_net'] ?? 0), + 'Versandkosten' => (float) ($order['amount_shipping'] ?? 0), + 'Mehrwertsteuer' => (float) ($order['amount_tax'] ?? 0), + 'Rabatt' => (float) ($order['amount_discount'] ?? 0), + 'Gesamtsumme' => (float) ($order['total_amount'] ?? 0), + 'lineItems' => $lineItems, + ], $address($addresses['shipping'] ?? [], 'LfAdr'), $address($addresses['billing'] ?? [], 'RgAdr')); +} + function dispatch_order_import_webhooks(PDO $pdo, array $localEnv, int $limit = 20): array { $url = derive_excel_webhook_url($localEnv); diff --git a/modules/erp/import-integration/shopify-delta-run.php b/modules/erp/import-integration/shopify-delta-run.php index 04b9fd9..3776a1c 100644 --- a/modules/erp/import-integration/shopify-delta-run.php +++ b/modules/erp/import-integration/shopify-delta-run.php @@ -3,6 +3,7 @@ declare(strict_types=1); require_once __DIR__ . '/../../../modules/shared/db.php'; require_once __DIR__ . '/shopify-api.php'; +require_once __DIR__ . '/service.php'; require_once __DIR__ . '/../bestellungen/shopify-projection.php'; function shopify_delta_argument(string $name, array $argv, ?string $default = null): ?string @@ -133,6 +134,16 @@ function run_shopify_delta(array $env, PDO $pdo, string $cutoff, bool $dryRun): static fn (string $gid): array => shopify_delta_load_order($env, $gid), $dryRun ); + if (!$dryRun && ($result['status'] ?? '') === 'imported') { + $labelPayload = build_legacy_label_order_payload($pdo, (int) $result['sales_order_id']); + $labelResult = trigger_shipping_label_flow($labelPayload, $env); + $excelResult = trigger_excel_webhook((string) ($summaryOrder['name'] ?? $orderGid), $env); + $result['label_trigger'] = $labelResult; + $result['excel_trigger'] = $excelResult; + if (!$labelResult['ok'] || !$excelResult['ok']) { + throw new RuntimeException('Mindestens ein n8n-Webhook ist fehlgeschlagen'); + } + } if (($result['status'] ?? '') === 'already_imported') { $counters['already_imported']++; } else {