Changeset 3507036
- Timestamp:
- 04/15/2026 11:45:17 AM (6 months ago)
- Location:
- sendo
- Files:
-
- 12 added
- 3 edited
-
tags/5.1.6 (added)
-
tags/5.1.6/assets (added)
-
tags/5.1.6/assets/css (added)
-
tags/5.1.6/assets/css/sendoasp-shipping.css (added)
-
tags/5.1.6/assets/js (added)
-
tags/5.1.6/assets/js/sendo-admin-order.js (added)
-
tags/5.1.6/assets/js/sendoasp-shipping.js (added)
-
tags/5.1.6/includes (added)
-
tags/5.1.6/includes/class-wc-shipping-sendoasp.php (added)
-
tags/5.1.6/languages (added)
-
tags/5.1.6/readme.txt (added)
-
tags/5.1.6/sendo.php (added)
-
trunk/includes/class-wc-shipping-sendoasp.php (modified) (1 diff)
-
trunk/readme.txt (modified) (4 diffs)
-
trunk/sendo.php (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sendo/trunk/includes/class-wc-shipping-sendoasp.php
r3491469 r3507036 13 13 14 14 if (!defined('SENDOASP_VERSION')) { 15 define('SENDOASP_VERSION', '5.1. 5');15 define('SENDOASP_VERSION', '5.1.6'); 16 16 } 17 17 -
sendo/trunk/readme.txt
r3491469 r3507036 1 1 === Sendo === 2 Contributors: shop123nettbutikker , phpwebdeveloper9002 Contributors: shop123nettbutikker 3 3 Tags: woocommerce, shipping, logistics 4 4 Requires at least: 5.8 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 5.1. 57 Stable tag: 5.1.6 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 51 51 * Pickup point auto-selection 52 52 * Pickup preference memory per postcode 53 * Automatic order transfer to Sendo on status change (configurable) 54 * Shipping method exclusion filter for auto-transfer 53 55 * Manual "Send to Sendo" button on admin order pages 54 56 * Re-send orders to Sendo with one click … … 76 78 77 79 == 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 78 87 79 88 = 5.1.5 = … … 117 126 == Upgrade Notice == 118 127 128 = 5.1.6 = 129 Adds 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 119 131 = 5.1.5 = 120 132 Real-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 4 4 * Plugin URI: https://sendo.no 5 5 * Description: Real-time shipping rates and pickup point selection from Sendo logistics platform. 6 * Version: 5.1. 56 * Version: 5.1.6 7 7 * Author: Sendo AS 8 8 * Text Domain: sendo … … 19 19 20 20 // Plugin constants 21 define('SENDOASP_VERSION', '5.1. 5');21 define('SENDOASP_VERSION', '5.1.6'); 22 22 define('SENDOASP_PLUGIN_FILE', __FILE__); 23 23 define('SENDOASP_PLUGIN_DIR', plugin_dir_path(__FILE__)); … … 93 93 add_action('wp_ajax_sendo_get_session_address', 'sendoaspGetSessionAddress'); 94 94 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(); 95 98 } 96 99 add_action('plugins_loaded', 'sendoaspInit', 20); … … 641 644 } 642 645 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 */ 666 function 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 */ 694 function 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 */ 726 function 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 */ 783 function sendoaspSendOrderToSendo($order) { 784 $order_id = $order->get_id(); 785 $creds = sendoaspGetApiCredentials(); 786 644 787 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 650 792 $shipping_list = ''; 651 793 foreach ($order->get_shipping_methods() as $sm) { … … 654 796 $shipping_list = trim($shipping_list); 655 797 798 // Recipient data — prefer shipping address, fall back to billing 656 799 $firstname = trim($order->get_shipping_first_name()) !== '' ? $order->get_shipping_first_name() : $order->get_billing_first_name(); 657 800 $lastname = trim($order->get_shipping_last_name()) !== '' ? $order->get_shipping_last_name() : $order->get_billing_last_name(); … … 665 808 $billcomp = $order->get_billing_company(); 666 809 810 // Collect line items with product data 667 811 $ship_items = array(); 668 812 foreach ($order->get_items() as $item) { … … 689 833 'H' => $product->get_height(), 690 834 'SHIPMENT_METHOD' => $shipping_list, 691 'HTTP_REFERER' => wp_get_referer(),692 835 ); 693 836 } 694 837 695 838 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 701 843 $url = 'https://www.frakt123.no/public/api/woo/index.php'; 702 844 703 845 $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()), 719 861 ); 720 862 … … 728 870 729 871 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); 731 873 } 732 874 … … 735 877 736 878 if (isset($res->error) && (int) $res->error === 0) { 737 // Store tracking data (HPOS-compatible )879 // Store tracking data (HPOS-compatible + legacy keys) 738 880 $order->update_meta_data('_sendo_tracking_id', $res->tracking_id); 739 881 $order->update_meta_data('_sendo_tracking_link', $res->tracking_link ?? ''); 740 741 // Also write legacy keys for backward compatibility742 882 $order->update_meta_data('frakt_track_id', $res->tracking_id); 743 883 $order->update_meta_data('frakt_track_link', $res->tracking_link ?? ''); 744 884 $order->save(); 745 885 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); 755 891 } 756 892
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)