gruene-seele/dev/partnercenter-api/public/woocommerce/order-status.php
Kevin Adametz 0c8d321f66 Warenwirtschaft: AP-38 — ERP-/Connector-Status-Mapping vervollständigt
Die orange Ampel bei abgeschlossenen Bestellungen ist KEIN ERP-Fehler: der
Endpoint /api/wp/status liefert für versendete Bestellungen bereits sent/close
(Live-DB: 111× shipped=2, 1× shipped=3). Ursache liegt shopseitig (Cron/Auth) —
wird per SSH geprüft. Unabhängig davon die latenten Mapping-Lücken geschlossen:

ERP (ShoppingOrder::$apiShippedTypes):
- Status 5 (Wartestellung) fehlte und lieferte den Default 'free' (im Shop gar
  kein Licht). Jetzt 5 => 'process' (Shop-Ampel orange = in Bearbeitung).

Connector (partnercenter-api, Teil von v1.6.0 — noch nicht ausgerollt):
- admin/post-list.php: Ampel-Switch deckt jetzt 'pick_up' (Abholung ⇒ grün) und
  'cancel' (storniert ⇒ neue rote Kugel) ab; vorher fielen beide auf ⚠️.
- woocommerce/order-status.php: 'pick_up' und 'cancel' gelten jetzt als
  Endzustände und fallen aus der stündlichen Nachfrage-Liste
  (_partnercenter_api_unclear_order_ids) — vorher wurden 12 stornierte
  Bestellungen dauerhaft weiter gepollt.

Test: AP-38-Mapping prüft alle shipped-Werte (kein stiller 'free'-Fallback mehr).
Suite 338 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 11:01:25 +00:00

284 lines
8.3 KiB
PHP

<?php
/*
* All order status related features.
*/
if (! defined('ABSPATH')) {
exit;
}
class PARTNERCENTER_API_WooCommerce_Order_Status_Class
{
/**
* PARTNERCENTER_API_WooCommerce_Order_Status_Class constructor.
*/
public function __construct()
{
// Listen to new orders
add_action('woocommerce_new_order', [$this, 'woocommerce_new_order'], 94839877, 2);
// Listen to order updates
add_action('woocommerce_update_order', [$this, 'woocommerce_update_order'], 94839877, 2);
// Listen to new orders by admin
add_action('woocommerce_process_shop_order_meta', [$this, 'woocommerce_process_shop_order_meta'], 9876, 1);
// Listen to button click
add_action('partnercenter_api_send_order_items', [$this, 'partnercenter_api_send_order_items'], 20, 1);
// Listen to button click
add_action('partnercenter_api_retrieve_order', [$this, 'partnercenter_api_retrieve_order'], 20, 1);
// Listen for cron event
add_action('partnercenter_api_fetch_orders_status', [$this, 'partnercenter_api_fetch_orders_status'], 20);
}
/**
* Run API request on new order.
*
* @param WC_Order order
*
* @since 1.0.0
*/
public function woocommerce_new_order(int $order_id, $order)
{
// Build a hash over addresses
$address_string = $order->get_formatted_billing_address().$order->get_formatted_shipping_address();
$new_address_hash = md5($address_string);
// Store hash of addresses as meta data
add_post_meta($order_id, '_partnercenter_api_address_hash', $new_address_hash, true);
// Load API
$partnercenter = apply_filters('PARTNERCENTER_API', false);
if ($partnercenter === false) {
return;
}
// Notify PARTNERCENTER about new order
$added = $partnercenter->new_order($order_id);
if ($added) {
// Add flag about sent order
update_post_meta($order_id, '_partnercenter_api_order_added', time());
}
}
/**
* Handle new orders from admin screen.
*
* @param $order_id integer
*/
public function woocommerce_process_shop_order_meta(int $order_id)
{
// Check if order needs handling- if value isset the order has been send to API on "thank you" page
if (! empty(get_post_meta($order_id, '_partnercenter_api_order_added', true))) {
return;
}
// Get order object
$order = new WC_Order($order_id);
// Check if email was given
if (empty($order->get_billing_email())) {
return;
}
// Load API
$partnercenter = apply_filters('PARTNERCENTER_API', false);
if ($partnercenter === false) {
return;
}
// Notify PARTNERCENTER about new order
$added = $partnercenter->new_order($order_id);
if ($added) {
// Add flag about sent order
update_post_meta($order_id, '_partnercenter_api_order_added', time());
}
}
/**
* Run API request on order update.
*
* @param WC_Order $order
*
* @since 1.0.0
*/
public function woocommerce_update_order(int $order_id, $order)
{
// Build a hash over addresses
$address_string = $order->get_formatted_billing_address().$order->get_formatted_shipping_address();
$new_address_hash = md5($address_string);
// Get old address hash
$old_address_hash = get_post_meta($order_id, '_partnercenter_api_address_hash', true);
// Check if address data has changed
if ($old_address_hash === $new_address_hash) {
// Address had not been changed
return;
}
// Update hash of addresses as meta data
update_post_meta($order_id, '_partnercenter_api_address_hash', $new_address_hash);
// Load API
$partnercenter = apply_filters('PARTNERCENTER_API', false);
if ($partnercenter === false) {
return;
}
// Notify PARTNERCENTER API about updated addresses
$partnercenter->update_order($order_id);
}
/**
* Run API request on order forwarding form action.
*
*
* @since 1.0.0
*/
public function partnercenter_api_send_order_items(int $order_id)
{
// Load API
$partnercenter = apply_filters('PARTNERCENTER_API', false);
if ($partnercenter === false) {
return;
}
// Notify PARTNERCENTER about order content
$received = $partnercenter->send_order_items($order_id);
// Exit on error
if ($received === false) {
return;
}
// Add a value to be overwritten by cron job
add_post_meta($order_id, '_partnercenter_api_order_status', 'open', true);
/*
* Add order ID to list of orders to check regularly
*/
// Get list of orders to add to
$unclear_orders = get_option('_partnercenter_api_unclear_order_ids', []);
// Add current order ID to list
$unclear_orders[] = intval($order_id);
// Save new list of unclear order ids
update_option('_partnercenter_api_unclear_order_ids', $unclear_orders, false);
}
/**
* Run API request to retrieve order from shipment.
*
*
* @since 1.2.0
*/
public function partnercenter_api_retrieve_order(int $order_id)
{
// Load API
$partnercenter = apply_filters('PARTNERCENTER_API', false);
if ($partnercenter === false) {
return;
}
// Notify PARTNERCENTER about retrieved order
$received = $partnercenter->retrieve_order($order_id);
// Exit on error
if ($received === false) {
return;
}
// Remove value to make order free again
delete_post_meta($order_id, '_partnercenter_api_order_status');
// Mark order to be canceled in API
update_post_meta($order_id, '_partnercenter_api_order_canceled', time());
/*
* Add order ID to list of orders to check regularly
*/
// Get list of orders to add to
$unclear_orders = get_option('_partnercenter_api_unclear_order_ids', []);
$found_key = array_search($order_id, $unclear_orders);
if ($found_key === false) {
return;
}
// Remove order from list of orders to check
unset($unclear_orders[$found_key]);
// Save new list of unclear order ids
update_option('_partnercenter_api_unclear_order_ids', $unclear_orders, false);
}
/**
* Handle cron event call.
*
* @since 1.0.0
*/
public function partnercenter_api_fetch_orders_status()
{
// Get list of unclear orders
$unclear_orders = get_option('_partnercenter_api_unclear_order_ids', []);
if (empty($unclear_orders)) {
// No orders to check
return;
}
// Load API
$partnercenter = apply_filters('PARTNERCENTER_API', false);
if ($partnercenter === false) {
return;
}
// Ask PARTNERCENTER about current status
$new_statuses = $partnercenter->get_orders_status($unclear_orders);
if (empty($new_statuses)) {
// No orders to check or connection error
return;
}
// Loop all received order statues
foreach ($new_statuses as $order_key => $order_status) {
// Store new status
update_post_meta($order_key, '_partnercenter_api_order_status', sanitize_title($order_status));
// AP-38: Endzustände aus der Nachfrage-Liste nehmen — sonst werden
// abgeholte/stornierte Bestellungen stündlich weiter abgefragt.
if (! in_array($order_status, ['close', 'sent', 'pick_up', 'cancel'])) {
continue;
}
// Search order ID in list of unclear orders
$key_in_array = array_search($order_key, $unclear_orders);
// Remove order after it shipped
unset($unclear_orders[$key_in_array]);
}
// Save new list of unclear order IDs
update_option('_partnercenter_api_unclear_order_ids', $unclear_orders, false);
}
}
new PARTNERCENTER_API_WooCommerce_Order_Status_Class;