Plugin Directory

Changeset 3507036


Ignore:
Timestamp:
04/15/2026 11:45:17 AM (6 months ago)
Author:
shop123nettbutikker
Message:

Auto send issue fixed

Location:
sendo
Files:
12 added
3 edited

Legend:

Unmodified
Added
Removed
  • sendo/trunk/includes/class-wc-shipping-sendoasp.php

    r3491469 r3507036  
    1313
    1414if (!defined('SENDOASP_VERSION')) {
    15     define('SENDOASP_VERSION', '5.1.5');
     15    define('SENDOASP_VERSION', '5.1.6');
    1616}
    1717
  • sendo/trunk/readme.txt

    r3491469 r3507036  
    11=== Sendo ===
    2 Contributors: shop123nettbutikker, phpwebdeveloper900
     2Contributors: shop123nettbutikker
    33Tags: woocommerce, shipping, logistics
    44Requires at least: 5.8
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 5.1.5
     7Stable tag: 5.1.6
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    5151* Pickup point auto-selection
    5252* Pickup preference memory per postcode
     53* Automatic order transfer to Sendo on status change (configurable)
     54* Shipping method exclusion filter for auto-transfer
    5355* Manual "Send to Sendo" button on admin order pages
    5456* Re-send orders to Sendo with one click
    … …  
    7678
    7779== Changelog ==
     80
     81= 5.1.6 =
     82* Automatic order transfer to Sendo when order status changes (completed, partial-shipped, or custom status)
     83* Configurable shipping method exclusion — skip auto-transfer for specific shipping methods
     84* Duplicate-send prevention — orders already sent to Sendo are not re-sent automatically
     85* Refactored order-send logic into shared sendoaspSendOrderToSendo() function (used by both manual and auto-transfer)
     86* Debug logging for auto-transfer success and failure events
    7887
    7988= 5.1.5 =
    … …  
    117126== Upgrade Notice ==
    118127
     128= 5.1.6 =
     129Adds automatic order transfer to Sendo on status change (completed, partial-shipped, or custom). Configure in Sendo shipping method settings. Existing manual send button continues to work.
     130
    119131= 5.1.5 =
    120132Real-time shipping rates are now off by default — enable per shipping zone if needed. Adds manual "Send to Sendo" button on admin order pages.
  • sendo/trunk/sendo.php

    r3491469 r3507036  
    44 * Plugin URI: https://sendo.no
    55 * Description: Real-time shipping rates and pickup point selection from Sendo logistics platform.
    6  * Version: 5.1.5
     6 * Version: 5.1.6
    77 * Author: Sendo AS
    88 * Text Domain: sendo
    … …  
    1919
    2020// Plugin constants
    21 define('SENDOASP_VERSION', '5.1.5');
     21define('SENDOASP_VERSION', '5.1.6');
    2222define('SENDOASP_PLUGIN_FILE', __FILE__);
    2323define('SENDOASP_PLUGIN_DIR', plugin_dir_path(__FILE__));
    … …  
    9393    add_action('wp_ajax_sendo_get_session_address', 'sendoaspGetSessionAddress');
    9494    add_action('wp_ajax_nopriv_sendo_get_session_address', 'sendoaspGetSessionAddress');
     95
     96    // ── Auto-transfer: hook into order status changes based on instance settings ──
     97    sendoaspRegisterAutoTransferHooks();
    9598}
    9699add_action('plugins_loaded', 'sendoaspInit', 20);
    … …  
    641644    }
    642645
    643     $creds = sendoaspGetApiCredentials();
     646    // Delegate to the shared send function
     647    $result = sendoaspSendOrderToSendo($order);
     648
     649    if ($result['success']) {
     650        wp_send_json_success(array(
     651            'message'       => sprintf(__('Ordren er sendt til Sendo (ID: %s)', 'sendo'), $result['tracking_id']),
     652            'tracking_id'   => $result['tracking_id'],
     653            'tracking_link' => $result['tracking_link'],
     654        ));
     655    } else {
     656        wp_send_json_error(array('message' => $result['message']));
     657    }
     658}
     659
     660/**
     661 * Retrieve the full settings array from the first enabled sendoasp shipping method instance.
     662 * Used by auto-transfer to read auto_send, order_status, and exclude_shipping_method.
     663 *
     664 * @return array|false  Settings array or false if no instance found.
     665 */
     666function sendoaspGetInstanceSettings() {
     667    global $wpdb;
     668
     669    $rows = $wpdb->get_results(
     670        "SELECT instance_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods
     671         WHERE method_id = 'sendoasp' AND is_enabled = 1
     672         ORDER BY method_order ASC LIMIT 1"
     673    );
     674
     675    if (empty($rows)) {
     676        return false;
     677    }
     678
     679    $instance_id = (int) $rows[0]->instance_id;
     680    $option_key  = 'woocommerce_sendoasp_' . $instance_id . '_settings';
     681    $settings    = get_option($option_key, array());
     682
     683    return is_array($settings) ? $settings : false;
     684}
     685
     686/**
     687 * Register auto-transfer hooks based on the Sendo shipping method instance settings.
     688 *
     689 * Reads the auto_send and order_status settings from the first enabled Sendo instance.
     690 * When auto_send is 'yes', hooks into woocommerce_order_status_completed and
     691 * woocommerce_order_status_partial-shipped. Additionally hooks into whatever custom
     692 * status is selected in the order_status setting (e.g. processing, on-hold).
     693 */
     694function sendoaspRegisterAutoTransferHooks() {
     695    $settings = sendoaspGetInstanceSettings();
     696    if (!$settings) {
     697        return;
     698    }
     699
     700    $auto_send = isset($settings['auto_send']) ? $settings['auto_send'] : 'no';
     701
     702    // Hook into completed and partial-shipped when auto_send is enabled
     703    if ($auto_send === 'yes') {
     704        add_action('woocommerce_order_status_completed', 'sendoaspAutoTransferOrder');
     705        add_action('woocommerce_order_status_partial-shipped', 'sendoaspAutoTransferOrder');
     706    }
     707
     708    // Hook into the custom-configured status (e.g. processing, on-hold)
     709    $order_status = isset($settings['order_status']) ? $settings['order_status'] : '';
     710    if (!empty($order_status)) {
     711        // Strip 'wc-' prefix if present (WooCommerce stores statuses as 'wc-processing' etc.)
     712        $status_slug = str_replace('wc-', '', $order_status);
     713        add_action('woocommerce_order_status_' . $status_slug, 'sendoaspAutoTransferOrder');
     714    }
     715}
     716
     717/**
     718 * Auto-transfer callback: sends an order to Sendo when its status changes.
     719 *
     720 * Checks the exclude_shipping_method setting — if the order's shipping method matches
     721 * the excluded method, the transfer is skipped. Also skips if the order was already
     722 * sent (has a _sendo_tracking_id). Reuses sendoaspSendOrderToSendo() for the actual POST.
     723 *
     724 * @param int $order_id WooCommerce order ID.
     725 */
     726function sendoaspAutoTransferOrder($order_id) {
     727    $order = wc_get_order($order_id);
     728    if (!$order) {
     729        return;
     730    }
     731
     732    // Skip if already sent to Sendo
     733    $existing_id = $order->get_meta('_sendo_tracking_id');
     734    if (!empty($existing_id)) {
     735        return;
     736    }
     737
     738    // Check shipping method exclusion filter
     739    $settings = sendoaspGetInstanceSettings();
     740    if ($settings) {
     741        $exclude_method = isset($settings['exclude_shipping_method']) ? $settings['exclude_shipping_method'] : '';
     742        if (!empty($exclude_method)) {
     743            $shipping_methods = $order->get_shipping_methods();
     744            $first_method = reset($shipping_methods);
     745            if ($first_method) {
     746                $method_id = $first_method->get_method_id();
     747                if ($method_id === $exclude_method) {
     748                    return;
     749                }
     750            }
     751        }
     752    }
     753
     754    // Send the order to Sendo
     755    $result = sendoaspSendOrderToSendo($order);
     756
     757    // Log the result if debug mode is enabled
     758    if (get_option('sendo_debug_mode', 'no') === 'yes') {
     759        $logger = wc_get_logger();
     760        if ($result['success']) {
     761            $logger->info(
     762                sprintf('Auto-transfer: Order #%d sent to Sendo (ID: %s)', $order_id, $result['tracking_id']),
     763                array('source' => 'sendo')
     764            );
     765        } else {
     766            $logger->error(
     767                sprintf('Auto-transfer: Order #%d failed — %s', $order_id, $result['message']),
     768                array('source' => 'sendo')
     769            );
     770        }
     771    }
     772}
     773
     774/**
     775 * Send an order to the Sendo API and store tracking data on success.
     776 *
     777 * This is the shared core logic used by both the manual AJAX send and the auto-transfer hook.
     778 * Collects order/recipient/item data, POSTs to Sendo, and writes tracking meta on success.
     779 *
     780 * @param WC_Order $order The WooCommerce order object.
     781 * @return array  ['success' => bool, 'message' => string, 'tracking_id' => string|null, 'tracking_link' => string|null]
     782 */
     783function sendoaspSendOrderToSendo($order) {
     784    $order_id = $order->get_id();
     785    $creds    = sendoaspGetApiCredentials();
     786
    644787    if (!$creds) {
    645         wp_send_json_error(array('message' => __('Sendo API-nøkler er ikke konfigurert. Gå til WooCommerce → Innstillinger → Frakt → Sendo.', 'sendo')));
    646     }
    647 
    648     // ── Gather order data (same format as the old frakt123 plugin) ──
    649 
     788        return array('success' => false, 'message' => 'Sendo API credentials not configured.', 'tracking_id' => null, 'tracking_link' => null);
     789    }
     790
     791    // Gather shipping method names
    650792    $shipping_list = '';
    651793    foreach ($order->get_shipping_methods() as $sm) {
    … …  
    654796    $shipping_list = trim($shipping_list);
    655797
     798    // Recipient data — prefer shipping address, fall back to billing
    656799    $firstname = trim($order->get_shipping_first_name()) !== '' ? $order->get_shipping_first_name() : $order->get_billing_first_name();
    657800    $lastname  = trim($order->get_shipping_last_name())  !== '' ? $order->get_shipping_last_name()  : $order->get_billing_last_name();
    … …  
    665808    $billcomp  = $order->get_billing_company();
    666809
     810    // Collect line items with product data
    667811    $ship_items = array();
    668812    foreach ($order->get_items() as $item) {
    … …  
    689833            'H'               => $product->get_height(),
    690834            'SHIPMENT_METHOD' => $shipping_list,
    691             'HTTP_REFERER'    => wp_get_referer(),
    692835        );
    693836    }
    694837
    695838    if (empty($ship_items)) {
    696         wp_send_json_error(array('message' => __('Ingen produkter i ordren, eller produktdata mangler.', 'sendo')));
    697     }
    698 
    699     // ── POST to Sendo API ──
    700 
     839        return array('success' => false, 'message' => 'No products in order or product data missing.', 'tracking_id' => null, 'tracking_link' => null);
     840    }
     841
     842    // POST to Sendo API
    701843    $url = 'https://www.frakt123.no/public/api/woo/index.php';
    702844
    703845    $post_param = array(
    704         'wp_key'        => $creds['api_key'],
    705         'wp_secret'     => $creds['api_secret'],
    706         'oid'           => $order_id,
    707         'wp_site'       => $creds['shop_url'],
    708         'ship_items'    => wp_json_encode($ship_items),
    709         'ship_clientnr' => $order->get_user_id(),
    710         'ship_firstname'=> $firstname !== '' ? $firstname : ($company !== '' ? $company : $billcomp),
    711         'ship_lastname' => $lastname,
    712         'ship_adr1'     => $address1,
    713         'ship_adr2'     => $address2,
    714         'ship_postnr'   => $postcode,
    715         'ship_city'     => $city,
    716         'ship_phone'    => $phone,
    717         'ship_email'    => $email,
    718         'order_date'    => strtotime($order->get_date_created()),
     846        'wp_key'         => $creds['api_key'],
     847        'wp_secret'      => $creds['api_secret'],
     848        'oid'            => $order_id,
     849        'wp_site'        => $creds['shop_url'],
     850        'ship_items'     => wp_json_encode($ship_items),
     851        'ship_clientnr'  => $order->get_user_id(),
     852        'ship_firstname' => $firstname !== '' ? $firstname : ($company !== '' ? $company : $billcomp),
     853        'ship_lastname'  => $lastname,
     854        'ship_adr1'      => $address1,
     855        'ship_adr2'      => $address2,
     856        'ship_postnr'    => $postcode,
     857        'ship_city'      => $city,
     858        'ship_phone'     => $phone,
     859        'ship_email'     => $email,
     860        'order_date'     => strtotime($order->get_date_created()),
    719861    );
    720862
    … …  
    728870
    729871    if (is_wp_error($response)) {
    730         wp_send_json_error(array('message' => $response->get_error_message()));
     872        return array('success' => false, 'message' => $response->get_error_message(), 'tracking_id' => null, 'tracking_link' => null);
    731873    }
    732874
    … …  
    735877
    736878    if (isset($res->error) && (int) $res->error === 0) {
    737         // Store tracking data (HPOS-compatible)
     879        // Store tracking data (HPOS-compatible + legacy keys)
    738880        $order->update_meta_data('_sendo_tracking_id', $res->tracking_id);
    739881        $order->update_meta_data('_sendo_tracking_link', $res->tracking_link ?? '');
    740 
    741         // Also write legacy keys for backward compatibility
    742882        $order->update_meta_data('frakt_track_id', $res->tracking_id);
    743883        $order->update_meta_data('frakt_track_link', $res->tracking_link ?? '');
    744884        $order->save();
    745885
    746         wp_send_json_success(array(
    747             'message'      => sprintf(__('Ordren er sendt til Sendo (ID: %s)', 'sendo'), $res->tracking_id),
    748             'tracking_id'  => $res->tracking_id,
    749             'tracking_link'=> $res->tracking_link ?? '',
    750         ));
    751     } else {
    752         $error_msg = isset($res->msg) ? $res->msg : __('Ukjent feil fra Sendo. Prøv igjen.', 'sendo');
    753         wp_send_json_error(array('message' => $error_msg));
    754     }
     886        return array('success' => true, 'message' => 'OK', 'tracking_id' => $res->tracking_id, 'tracking_link' => $res->tracking_link ?? '');
     887    }
     888
     889    $error_msg = isset($res->msg) ? $res->msg : 'Unknown error from Sendo.';
     890    return array('success' => false, 'message' => $error_msg, 'tracking_id' => null, 'tracking_link' => null);
    755891}
    756892
Note: See TracChangeset for help on using the changeset viewer.