Changeset 3411298
- Timestamp:
- 12/04/2025 06:16:00 PM (3 months ago)
- Location:
- jne-shipping-official
- Files:
-
- 11 edited
- 29 copied
-
tags/1.2.1 (copied) (copied from jne-shipping-official/trunk)
-
tags/1.2.1/LICENSE.txt (copied) (copied from jne-shipping-official/trunk/LICENSE.txt)
-
tags/1.2.1/admin (copied) (copied from jne-shipping-official/trunk/admin)
-
tags/1.2.1/admin/class-jne-woocommerce-admin.php (copied) (copied from jne-shipping-official/trunk/admin/class-jne-woocommerce-admin.php) (5 diffs)
-
tags/1.2.1/admin/includes/class-jne-admin-dashboard.php (copied) (copied from jne-shipping-official/trunk/admin/includes/class-jne-admin-dashboard.php)
-
tags/1.2.1/admin/includes/class-jne-admin-generate-awb.php (copied) (copied from jne-shipping-official/trunk/admin/includes/class-jne-admin-generate-awb.php) (2 diffs)
-
tags/1.2.1/admin/includes/class-jne-admin-generate-cnote.php (copied) (copied from jne-shipping-official/trunk/admin/includes/class-jne-admin-generate-cnote.php)
-
tags/1.2.1/admin/includes/class-jne-admin-order-helper.php (copied) (copied from jne-shipping-official/trunk/admin/includes/class-jne-admin-order-helper.php)
-
tags/1.2.1/admin/includes/class-jne-admin-order-list.php (copied) (copied from jne-shipping-official/trunk/admin/includes/class-jne-admin-order-list.php) (1 diff)
-
tags/1.2.1/admin/includes/class-jne-admin-shipping-method.php (copied) (copied from jne-shipping-official/trunk/admin/includes/class-jne-admin-shipping-method.php) (2 diffs)
-
tags/1.2.1/admin/partials/jne-woocommerce-admin-dashboard-display.php (copied) (copied from jne-shipping-official/trunk/admin/partials/jne-woocommerce-admin-dashboard-display.php)
-
tags/1.2.1/admin/partials/jne-woocommerce-admin-support-display.php (copied) (copied from jne-shipping-official/trunk/admin/partials/jne-woocommerce-admin-support-display.php)
-
tags/1.2.1/admin/partials/jne-woocommerce-admin-webhook-logs-display.php (copied) (copied from jne-shipping-official/trunk/admin/partials/jne-woocommerce-admin-webhook-logs-display.php)
-
tags/1.2.1/assets (copied) (copied from jne-shipping-official/trunk/assets)
-
tags/1.2.1/composer.json (copied) (copied from jne-shipping-official/trunk/composer.json) (1 diff)
-
tags/1.2.1/composer.lock (copied) (copied from jne-shipping-official/trunk/composer.lock)
-
tags/1.2.1/includes (copied) (copied from jne-shipping-official/trunk/includes)
-
tags/1.2.1/includes/class-jne-woocommerce-api.php (modified) (2 diffs)
-
tags/1.2.1/includes/class-jne-woocommerce-webhook-logger.php (copied) (copied from jne-shipping-official/trunk/includes/class-jne-woocommerce-webhook-logger.php)
-
tags/1.2.1/includes/class-jne-woocommerce-webhook.php (copied) (copied from jne-shipping-official/trunk/includes/class-jne-woocommerce-webhook.php)
-
tags/1.2.1/includes/class-jne-woocommerce.php (copied) (copied from jne-shipping-official/trunk/includes/class-jne-woocommerce.php)
-
tags/1.2.1/index.php (copied) (copied from jne-shipping-official/trunk/index.php)
-
tags/1.2.1/jne-shipping-official.php (copied) (copied from jne-shipping-official/trunk/jne-shipping-official.php) (2 diffs)
-
tags/1.2.1/languages (copied) (copied from jne-shipping-official/trunk/languages)
-
tags/1.2.1/public (copied) (copied from jne-shipping-official/trunk/public)
-
tags/1.2.1/public/class-jne-woocommerce-public.php (modified) (2 diffs)
-
tags/1.2.1/public/includes/jne-woocommerce-public-cod.php (copied) (copied from jne-shipping-official/trunk/public/includes/jne-woocommerce-public-cod.php)
-
tags/1.2.1/public/includes/jne-woocommerce-public-insurance.php (copied) (copied from jne-shipping-official/trunk/public/includes/jne-woocommerce-public-insurance.php)
-
tags/1.2.1/readme.txt (copied) (copied from jne-shipping-official/trunk/readme.txt) (2 diffs)
-
tags/1.2.1/uninstall.php (copied) (copied from jne-shipping-official/trunk/uninstall.php)
-
tags/1.2.1/vendor (copied) (copied from jne-shipping-official/trunk/vendor)
-
trunk/admin/class-jne-woocommerce-admin.php (modified) (5 diffs)
-
trunk/admin/includes/class-jne-admin-generate-awb.php (modified) (2 diffs)
-
trunk/admin/includes/class-jne-admin-order-list.php (modified) (1 diff)
-
trunk/admin/includes/class-jne-admin-shipping-method.php (modified) (2 diffs)
-
trunk/composer.json (modified) (1 diff)
-
trunk/includes/class-jne-woocommerce-api.php (modified) (2 diffs)
-
trunk/jne-shipping-official.php (modified) (2 diffs)
-
trunk/public/class-jne-woocommerce-public.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
jne-shipping-official/tags/1.2.1/admin/class-jne-woocommerce-admin.php
r3399074 r3411298 64 64 add_action('wp_ajax_jneshof_edit_customer', [$this, 'ajax_edit_customer']); 65 65 add_action('wp_ajax_jneshof_delete_customer', [$this, 'ajax_delete_customer']); 66 add_action('wp_ajax_jneshof_get_provinces', [$this, 'ajax_get_provinces']); 67 add_action('wp_ajax_jneshof_get_cities', [$this, 'ajax_get_cities']); 68 add_action('wp_ajax_jneshof_get_districts', [$this, 'ajax_get_districts']); 69 add_action('wp_ajax_jneshof_save_adjustment', [$this, 'ajax_save_adjustment']); 70 add_action('wp_ajax_jneshof_delete_adjustment', [$this, 'ajax_delete_adjustment']); 66 71 67 72 add_action('admin_footer', [$this, 'hide_wp_footer']); … … 113 118 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-generate-awb.php'; 114 119 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-dashboard.php'; 120 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-shipping-cost-adjustment.php'; 115 121 } 116 122 … … 398 404 add_submenu_page( 399 405 'jneshof-landing', 406 __('Shipping Cost Adjustments', 'jne-shipping-official'), 407 __('Shipping Cost Adjustments', 'jne-shipping-official'), 408 'manage_options', 409 'jneshof-shipping-cost-adjustments', 410 [$this, 'display_shipping_cost_adjustments_page'] 411 ); 412 add_submenu_page( 413 'jneshof-landing', 400 414 __('Bantuan', 'jne-shipping-official'), 401 415 __('Bantuan', 'jne-shipping-official'), … … 449 463 { 450 464 return include_once plugin_dir_path(__FILE__) . 'partials/jne-woocommerce-admin-dashboard-display.php'; 465 } 466 467 public function display_shipping_cost_adjustments_page() 468 { 469 return include_once plugin_dir_path(__FILE__) . 'partials/jne-woocommerce-admin-shipping-cost-adjustments-display.php'; 451 470 } 452 471 … … 782 801 * AJAX handler for deleting customer ID 783 802 */ 803 /** 804 * AJAX handler for getting provinces 805 */ 806 public function ajax_get_provinces() 807 { 808 if (!current_user_can('manage_options')) { 809 wp_send_json_error('Insufficient permissions'); 810 return; 811 } 812 813 $api = Jneshof_Woocommerce_API::get_instance(); 814 $provinces = $api->get_provinces(); 815 816 if (is_wp_error($provinces)) { 817 wp_send_json_error($provinces->get_error_message()); 818 return; 819 } 820 821 wp_send_json_success($provinces); 822 } 823 824 /** 825 * AJAX handler for getting cities 826 */ 827 public function ajax_get_cities() 828 { 829 if (!current_user_can('manage_options')) { 830 wp_send_json_error('Insufficient permissions'); 831 return; 832 } 833 834 $province_code = absint($_GET['province_code'] ?? 0); 835 $page = absint($_GET['page'] ?? 1); 836 $per_page = absint($_GET['per_page'] ?? 10); 837 $search = sanitize_text_field($_GET['search'] ?? ''); 838 839 if (empty($province_code)) { 840 wp_send_json_error('Province code is required'); 841 return; 842 } 843 844 $api = Jneshof_Woocommerce_API::get_instance(); 845 $response = $api->get_cities($province_code, $page, $per_page, $search); 846 847 if (is_wp_error($response)) { 848 wp_send_json_error($response->get_error_message()); 849 return; 850 } 851 852 wp_send_json_success($response); 853 } 854 855 /** 856 * AJAX handler for getting districts 857 */ 858 public function ajax_get_districts() 859 { 860 if (!current_user_can('manage_options')) { 861 wp_send_json_error('Insufficient permissions'); 862 return; 863 } 864 865 $province_code = absint($_GET['province_code'] ?? 0); 866 $city_name = sanitize_text_field($_GET['city_name'] ?? ''); 867 $page = absint($_GET['page'] ?? 1); 868 $per_page = absint($_GET['per_page'] ?? 10); 869 $search = sanitize_text_field($_GET['search'] ?? ''); 870 871 if (empty($province_code) || empty($city_name)) { 872 wp_send_json_error('Province code and city name are required'); 873 return; 874 } 875 876 $api = Jneshof_Woocommerce_API::get_instance(); 877 $response = $api->get_districts($province_code, $city_name, $page, $per_page, $search); 878 879 if (is_wp_error($response)) { 880 wp_send_json_error($response->get_error_message()); 881 return; 882 } 883 884 wp_send_json_success($response); 885 } 886 887 /** 888 * AJAX handler for saving adjustment 889 */ 890 public function ajax_save_adjustment() 891 { 892 if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'jneshof_adjustment_nonce')) { 893 wp_send_json_error('Security check failed'); 894 return; 895 } 896 897 if (!current_user_can('manage_options')) { 898 wp_send_json_error('Insufficient permissions'); 899 return; 900 } 901 902 $adjustment_handler = Jneshof_Admin_Shipping_Cost_Adjustment::get_instance(); 903 904 $data = [ 905 'id' => sanitize_text_field(wp_unslash($_POST['id'] ?? '')), 906 'name' => sanitize_text_field(wp_unslash($_POST['name'] ?? '')), 907 'adjustment_type' => sanitize_text_field(wp_unslash($_POST['adjustment_type'] ?? '')), 908 'adjustment_value' => floatval($_POST['adjustment_value'] ?? 0), 909 'is_active' => isset($_POST['is_active']) && (intval($_POST['is_active']) === 1) ? 1 : 0, 910 'date_from' => sanitize_text_field(wp_unslash($_POST['date_from'] ?? '')), 911 'date_to' => sanitize_text_field(wp_unslash($_POST['date_to'] ?? '')), 912 'services' => isset($_POST['services']) ? array_map('sanitize_text_field', (array) $_POST['services']) : [], 913 'provinces' => isset($_POST['provinces']) ? $this->sanitize_provinces($_POST['provinces']) : [], 914 'cities' => isset($_POST['cities']) ? array_map('sanitize_text_field', (array) $_POST['cities']) : [], 915 'districts' => isset($_POST['districts']) ? array_map('sanitize_text_field', (array) $_POST['districts']) : [], 916 ]; 917 918 $id = $adjustment_handler->save_adjustment($data); 919 920 if ($id) { 921 wp_send_json_success(['id' => $id, 'message' => 'Adjustment saved successfully']); 922 } else { 923 wp_send_json_error('Failed to save adjustment'); 924 } 925 } 926 927 /** 928 * AJAX handler for deleting adjustment 929 */ 930 public function ajax_delete_adjustment() 931 { 932 if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'jneshof_adjustment_nonce')) { 933 wp_send_json_error('Security check failed'); 934 return; 935 } 936 937 if (!current_user_can('manage_options')) { 938 wp_send_json_error('Insufficient permissions'); 939 return; 940 } 941 942 $id = sanitize_text_field(wp_unslash($_POST['id'] ?? '')); 943 944 if (empty($id)) { 945 wp_send_json_error('Adjustment ID is required'); 946 return; 947 } 948 949 $adjustment_handler = Jneshof_Admin_Shipping_Cost_Adjustment::get_instance(); 950 $deleted = $adjustment_handler->delete_adjustment($id); 951 952 if ($deleted) { 953 wp_send_json_success(['message' => 'Adjustment deleted successfully']); 954 } else { 955 wp_send_json_error('Failed to delete adjustment'); 956 } 957 } 958 959 /** 960 * Sanitize provinces data 961 */ 962 private function sanitize_provinces($provinces) 963 { 964 if (!is_array($provinces)) { 965 return []; 966 } 967 968 $sanitized = []; 969 foreach ($provinces as $province) { 970 if ($province === 'all') { 971 $sanitized[] = 'all'; 972 } elseif (is_array($province)) { 973 $sanitized[] = [ 974 'code' => absint($province['code'] ?? 0), 975 'name' => sanitize_text_field($province['name'] ?? '') 976 ]; 977 } elseif (is_string($province)) { 978 $sanitized[] = sanitize_text_field($province); 979 } 980 } 981 return $sanitized; 982 } 983 784 984 public function ajax_delete_customer() 785 985 { -
jne-shipping-official/tags/1.2.1/admin/includes/class-jne-admin-generate-awb.php
r3398965 r3411298 58 58 } 59 59 60 // Check if order already has tracking number 60 61 $jne_tracking_number = $order->getJNETrackingNumber(); 61 if ( !$jne_tracking_number) {62 $skipped_orders[] = "Order #$order_id: No JNE tracking number ";62 if (empty($jne_tracking_number)) { 63 $skipped_orders[] = "Order #$order_id: No JNE tracking number. Please generate CNote first to create shipping label."; 63 64 continue; 64 65 } … … 136 137 } 137 138 139 // Check if order already has tracking number 138 140 $jne_tracking_number = $order->getJNETrackingNumber(); 139 if ( !$jne_tracking_number) {140 wp_die(' JNE tracking number not found');141 if (empty($jne_tracking_number)) { 142 wp_die('Order does not have a JNE tracking number. Please generate CNote first to create shipping label.'); 141 143 } 142 144 -
jne-shipping-official/tags/1.2.1/admin/includes/class-jne-admin-order-list.php
r3399074 r3411298 324 324 } 325 325 326 // Check if order already has tracking number 326 327 $jne_tracking_number = $order->getJNETrackingNumber(); 327 if( !$jne_tracking_number) {328 throw new Exception(' JNE tracking number not found');328 if(empty($jne_tracking_number)) { 329 throw new Exception('Order does not have a JNE tracking number. Please generate shipping label (AWB) first before requesting pickup.'); 329 330 } 330 331 -
jne-shipping-official/tags/1.2.1/admin/includes/class-jne-admin-shipping-method.php
r3398965 r3411298 2 2 3 3 if (!defined('ABSPATH')) { 4 exit; 4 exit; 5 } 6 7 // Load adjustment handler if not already loaded 8 if (!class_exists('Jneshof_Admin_Shipping_Cost_Adjustment')) { 9 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-shipping-cost-adjustment.php'; 5 10 } 6 11 … … 148 153 149 154 // Only add rate if price is valid 150 if ($price > 0) { 155 // Note: Shipping cost adjustments will be applied as cart fees (similar to insurance) 156 if ($price >= 0) { 151 157 $this->add_rate([ 152 158 'id' => $this->id . ':' . $original_service_code, -
jne-shipping-official/tags/1.2.1/composer.json
r3399074 r3411298 2 2 "name": "jne-shipping/jne-shipping-official", 3 3 "description": "WordPress plugin integrated with WooCommerce for JNE shipping services", 4 "version": "1. 1.0",4 "version": "1.2.1", 5 5 "type": "wordpress-plugin", 6 6 "license": "GPL-2.0+", -
jne-shipping-official/tags/1.2.1/includes/class-jne-woocommerce-api.php
r3387194 r3411298 191 191 } 192 192 193 public function get_provinces()194 {195 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key();196 197 return $this->request('/v1/jne/provinces', [], 'GET', [198 'Authorization' => $access_key199 ]);200 }201 202 193 public function get_tariff_by_zipcode($destination_zipcode, $weight) 203 194 { … … 253 244 254 245 /** 246 * Get provinces 247 * @return array|WP_Error 248 */ 249 public function get_provinces() 250 { 251 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key(); 252 253 $response = $this->request('/v1/jne/provinces', [], 'GET', [ 254 'Authorization' => $access_key 255 ]); 256 257 if (is_wp_error($response)) { 258 return []; 259 } 260 261 return $response['data'] ?? []; 262 } 263 264 /** 265 * Get cities 266 * @param int $province_code 267 * @param int $page 268 * @param int $per_page 269 * @param string $search 270 * @return array|WP_Error 271 */ 272 public function get_cities($province_code, $page = 1, $per_page = 10, $search = '') 273 { 274 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key(); 275 276 $params = [ 277 'page' => $page, 278 'per_page' => $per_page, 279 'province_code' => $province_code 280 ]; 281 282 if (!empty($search)) { 283 $params['search'] = $search; 284 } 285 286 $query_string = '?' . http_build_query($params); 287 288 return $this->request('/v1/jne/cities' . $query_string, [], 'GET', [ 289 'Authorization' => $access_key 290 ]); 291 } 292 293 /** 294 * Get districts 295 * @param int $province_code 296 * @param string $city_name 297 * @param int $page 298 * @param int $per_page 299 * @param string $search 300 * @return array|WP_Error 301 */ 302 public function get_districts($province_code, $city_name, $page = 1, $per_page = 10, $search = '') 303 { 304 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key(); 305 306 $params = [ 307 'page' => $page, 308 'per_page' => $per_page, 309 'province_code' => $province_code, 310 'city_name' => $city_name 311 ]; 312 313 if (!empty($search)) { 314 $params['search'] = $search; 315 } 316 317 $query_string = '?' . http_build_query($params); 318 319 return $this->request('/v1/jne/districts' . $query_string, [], 'GET', [ 320 'Authorization' => $access_key 321 ]); 322 } 323 324 /** 255 325 * Generate cnote 256 326 * @param array $data -
jne-shipping-official/tags/1.2.1/jne-shipping-official.php
r3399074 r3411298 20 20 * Plugin Name: JNE Shipping Official 21 21 * Description: WordPress plugin integrated with WooCommerce for JNE shipping services 22 * Version: 1. 1.022 * Version: 1.2.1 23 23 * Author: PT. Tiki Jalur Nugraha Ekakurir 24 24 * Author URI: https://jne.co.id/ … … 48 48 * Rename this for your plugin and update it as you release new versions. 49 49 */ 50 define('JNESHOF_PLUGIN_VERSION', '1. 1.0');50 define('JNESHOF_PLUGIN_VERSION', '1.2.1'); 51 51 52 52 /** -
jne-shipping-official/tags/1.2.1/public/class-jne-woocommerce-public.php
r3387194 r3411298 68 68 Jneshof_Checkout_Shipping_Insurance::get_instance(); 69 69 } 70 if (class_exists('Jneshof_Checkout_Shipping_Cost_Adjustment')) { 71 Jneshof_Checkout_Shipping_Cost_Adjustment::get_instance(); 72 } 70 73 if (class_exists('Jneshof_Admin_Generate_Cnote')) { 71 74 Jneshof_Admin_Generate_Cnote::get_instance(); … … 78 81 require_once plugin_dir_path(dirname(__FILE__)) . 'public/includes/jne-woocommerce-public-cod.php'; 79 82 require_once plugin_dir_path(dirname(__FILE__)) . 'public/includes/jne-woocommerce-public-insurance.php'; 83 require_once plugin_dir_path(dirname(__FILE__)) . 'public/includes/jne-woocommerce-public-shipping-cost-adjustment.php'; 80 84 } 81 85 -
jne-shipping-official/tags/1.2.1/readme.txt
r3399074 r3411298 6 6 Tested up to: 6.8 7 7 Requires PHP: 7.4 8 Stable tag: 1. 1.08 Stable tag: 1.2.1 9 9 License: GPL-2.0+ 10 10 License URI: http://www.gnu.org/licenses/gpl-2.0.txt … … 90 90 91 91 == Changelog == 92 93 = 1.2.1 = 94 * Added validation to check if order has tracking number before requesting pickup 95 * Added validation to check if order has tracking number before generating shipping label (AWB) 96 * Improved error messages to guide users to generate CNote first when tracking number is missing 97 * Enhanced bulk AWB generation to skip orders without tracking numbers with clear error messages 98 99 = 1.2.0 = 100 * Added Shipping Cost Adjustments feature - Create and manage adjustment profiles to modify shipping costs 101 * Support for multiple adjustment types: Free Shipping, Add/Subtract Fixed Amount, Add/Subtract Percentage 102 * Flexible condition matching based on Services, Provinces, Cities, and Districts 103 * Date range support for time-limited adjustments 104 * Active/Inactive toggle for each adjustment profile 105 * Dual list box interface for selecting cities and districts (add/remove mechanism) 106 * Automatic application of adjustments as cart fees 107 * Adjustment rates are displayed as "Shipping Cost Discount" or "Shipping Cost Addition" in cart/checkout 92 108 93 109 = 1.1.0 = -
jne-shipping-official/trunk/admin/class-jne-woocommerce-admin.php
r3399074 r3411298 64 64 add_action('wp_ajax_jneshof_edit_customer', [$this, 'ajax_edit_customer']); 65 65 add_action('wp_ajax_jneshof_delete_customer', [$this, 'ajax_delete_customer']); 66 add_action('wp_ajax_jneshof_get_provinces', [$this, 'ajax_get_provinces']); 67 add_action('wp_ajax_jneshof_get_cities', [$this, 'ajax_get_cities']); 68 add_action('wp_ajax_jneshof_get_districts', [$this, 'ajax_get_districts']); 69 add_action('wp_ajax_jneshof_save_adjustment', [$this, 'ajax_save_adjustment']); 70 add_action('wp_ajax_jneshof_delete_adjustment', [$this, 'ajax_delete_adjustment']); 66 71 67 72 add_action('admin_footer', [$this, 'hide_wp_footer']); … … 113 118 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-generate-awb.php'; 114 119 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-dashboard.php'; 120 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-shipping-cost-adjustment.php'; 115 121 } 116 122 … … 398 404 add_submenu_page( 399 405 'jneshof-landing', 406 __('Shipping Cost Adjustments', 'jne-shipping-official'), 407 __('Shipping Cost Adjustments', 'jne-shipping-official'), 408 'manage_options', 409 'jneshof-shipping-cost-adjustments', 410 [$this, 'display_shipping_cost_adjustments_page'] 411 ); 412 add_submenu_page( 413 'jneshof-landing', 400 414 __('Bantuan', 'jne-shipping-official'), 401 415 __('Bantuan', 'jne-shipping-official'), … … 449 463 { 450 464 return include_once plugin_dir_path(__FILE__) . 'partials/jne-woocommerce-admin-dashboard-display.php'; 465 } 466 467 public function display_shipping_cost_adjustments_page() 468 { 469 return include_once plugin_dir_path(__FILE__) . 'partials/jne-woocommerce-admin-shipping-cost-adjustments-display.php'; 451 470 } 452 471 … … 782 801 * AJAX handler for deleting customer ID 783 802 */ 803 /** 804 * AJAX handler for getting provinces 805 */ 806 public function ajax_get_provinces() 807 { 808 if (!current_user_can('manage_options')) { 809 wp_send_json_error('Insufficient permissions'); 810 return; 811 } 812 813 $api = Jneshof_Woocommerce_API::get_instance(); 814 $provinces = $api->get_provinces(); 815 816 if (is_wp_error($provinces)) { 817 wp_send_json_error($provinces->get_error_message()); 818 return; 819 } 820 821 wp_send_json_success($provinces); 822 } 823 824 /** 825 * AJAX handler for getting cities 826 */ 827 public function ajax_get_cities() 828 { 829 if (!current_user_can('manage_options')) { 830 wp_send_json_error('Insufficient permissions'); 831 return; 832 } 833 834 $province_code = absint($_GET['province_code'] ?? 0); 835 $page = absint($_GET['page'] ?? 1); 836 $per_page = absint($_GET['per_page'] ?? 10); 837 $search = sanitize_text_field($_GET['search'] ?? ''); 838 839 if (empty($province_code)) { 840 wp_send_json_error('Province code is required'); 841 return; 842 } 843 844 $api = Jneshof_Woocommerce_API::get_instance(); 845 $response = $api->get_cities($province_code, $page, $per_page, $search); 846 847 if (is_wp_error($response)) { 848 wp_send_json_error($response->get_error_message()); 849 return; 850 } 851 852 wp_send_json_success($response); 853 } 854 855 /** 856 * AJAX handler for getting districts 857 */ 858 public function ajax_get_districts() 859 { 860 if (!current_user_can('manage_options')) { 861 wp_send_json_error('Insufficient permissions'); 862 return; 863 } 864 865 $province_code = absint($_GET['province_code'] ?? 0); 866 $city_name = sanitize_text_field($_GET['city_name'] ?? ''); 867 $page = absint($_GET['page'] ?? 1); 868 $per_page = absint($_GET['per_page'] ?? 10); 869 $search = sanitize_text_field($_GET['search'] ?? ''); 870 871 if (empty($province_code) || empty($city_name)) { 872 wp_send_json_error('Province code and city name are required'); 873 return; 874 } 875 876 $api = Jneshof_Woocommerce_API::get_instance(); 877 $response = $api->get_districts($province_code, $city_name, $page, $per_page, $search); 878 879 if (is_wp_error($response)) { 880 wp_send_json_error($response->get_error_message()); 881 return; 882 } 883 884 wp_send_json_success($response); 885 } 886 887 /** 888 * AJAX handler for saving adjustment 889 */ 890 public function ajax_save_adjustment() 891 { 892 if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'jneshof_adjustment_nonce')) { 893 wp_send_json_error('Security check failed'); 894 return; 895 } 896 897 if (!current_user_can('manage_options')) { 898 wp_send_json_error('Insufficient permissions'); 899 return; 900 } 901 902 $adjustment_handler = Jneshof_Admin_Shipping_Cost_Adjustment::get_instance(); 903 904 $data = [ 905 'id' => sanitize_text_field(wp_unslash($_POST['id'] ?? '')), 906 'name' => sanitize_text_field(wp_unslash($_POST['name'] ?? '')), 907 'adjustment_type' => sanitize_text_field(wp_unslash($_POST['adjustment_type'] ?? '')), 908 'adjustment_value' => floatval($_POST['adjustment_value'] ?? 0), 909 'is_active' => isset($_POST['is_active']) && (intval($_POST['is_active']) === 1) ? 1 : 0, 910 'date_from' => sanitize_text_field(wp_unslash($_POST['date_from'] ?? '')), 911 'date_to' => sanitize_text_field(wp_unslash($_POST['date_to'] ?? '')), 912 'services' => isset($_POST['services']) ? array_map('sanitize_text_field', (array) $_POST['services']) : [], 913 'provinces' => isset($_POST['provinces']) ? $this->sanitize_provinces($_POST['provinces']) : [], 914 'cities' => isset($_POST['cities']) ? array_map('sanitize_text_field', (array) $_POST['cities']) : [], 915 'districts' => isset($_POST['districts']) ? array_map('sanitize_text_field', (array) $_POST['districts']) : [], 916 ]; 917 918 $id = $adjustment_handler->save_adjustment($data); 919 920 if ($id) { 921 wp_send_json_success(['id' => $id, 'message' => 'Adjustment saved successfully']); 922 } else { 923 wp_send_json_error('Failed to save adjustment'); 924 } 925 } 926 927 /** 928 * AJAX handler for deleting adjustment 929 */ 930 public function ajax_delete_adjustment() 931 { 932 if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'jneshof_adjustment_nonce')) { 933 wp_send_json_error('Security check failed'); 934 return; 935 } 936 937 if (!current_user_can('manage_options')) { 938 wp_send_json_error('Insufficient permissions'); 939 return; 940 } 941 942 $id = sanitize_text_field(wp_unslash($_POST['id'] ?? '')); 943 944 if (empty($id)) { 945 wp_send_json_error('Adjustment ID is required'); 946 return; 947 } 948 949 $adjustment_handler = Jneshof_Admin_Shipping_Cost_Adjustment::get_instance(); 950 $deleted = $adjustment_handler->delete_adjustment($id); 951 952 if ($deleted) { 953 wp_send_json_success(['message' => 'Adjustment deleted successfully']); 954 } else { 955 wp_send_json_error('Failed to delete adjustment'); 956 } 957 } 958 959 /** 960 * Sanitize provinces data 961 */ 962 private function sanitize_provinces($provinces) 963 { 964 if (!is_array($provinces)) { 965 return []; 966 } 967 968 $sanitized = []; 969 foreach ($provinces as $province) { 970 if ($province === 'all') { 971 $sanitized[] = 'all'; 972 } elseif (is_array($province)) { 973 $sanitized[] = [ 974 'code' => absint($province['code'] ?? 0), 975 'name' => sanitize_text_field($province['name'] ?? '') 976 ]; 977 } elseif (is_string($province)) { 978 $sanitized[] = sanitize_text_field($province); 979 } 980 } 981 return $sanitized; 982 } 983 784 984 public function ajax_delete_customer() 785 985 { -
jne-shipping-official/trunk/admin/includes/class-jne-admin-generate-awb.php
r3398965 r3411298 58 58 } 59 59 60 // Check if order already has tracking number 60 61 $jne_tracking_number = $order->getJNETrackingNumber(); 61 if ( !$jne_tracking_number) {62 $skipped_orders[] = "Order #$order_id: No JNE tracking number ";62 if (empty($jne_tracking_number)) { 63 $skipped_orders[] = "Order #$order_id: No JNE tracking number. Please generate CNote first to create shipping label."; 63 64 continue; 64 65 } … … 136 137 } 137 138 139 // Check if order already has tracking number 138 140 $jne_tracking_number = $order->getJNETrackingNumber(); 139 if ( !$jne_tracking_number) {140 wp_die(' JNE tracking number not found');141 if (empty($jne_tracking_number)) { 142 wp_die('Order does not have a JNE tracking number. Please generate CNote first to create shipping label.'); 141 143 } 142 144 -
jne-shipping-official/trunk/admin/includes/class-jne-admin-order-list.php
r3399074 r3411298 324 324 } 325 325 326 // Check if order already has tracking number 326 327 $jne_tracking_number = $order->getJNETrackingNumber(); 327 if( !$jne_tracking_number) {328 throw new Exception(' JNE tracking number not found');328 if(empty($jne_tracking_number)) { 329 throw new Exception('Order does not have a JNE tracking number. Please generate shipping label (AWB) first before requesting pickup.'); 329 330 } 330 331 -
jne-shipping-official/trunk/admin/includes/class-jne-admin-shipping-method.php
r3398965 r3411298 2 2 3 3 if (!defined('ABSPATH')) { 4 exit; 4 exit; 5 } 6 7 // Load adjustment handler if not already loaded 8 if (!class_exists('Jneshof_Admin_Shipping_Cost_Adjustment')) { 9 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/includes/class-jne-admin-shipping-cost-adjustment.php'; 5 10 } 6 11 … … 148 153 149 154 // Only add rate if price is valid 150 if ($price > 0) { 155 // Note: Shipping cost adjustments will be applied as cart fees (similar to insurance) 156 if ($price >= 0) { 151 157 $this->add_rate([ 152 158 'id' => $this->id . ':' . $original_service_code, -
jne-shipping-official/trunk/composer.json
r3399074 r3411298 2 2 "name": "jne-shipping/jne-shipping-official", 3 3 "description": "WordPress plugin integrated with WooCommerce for JNE shipping services", 4 "version": "1. 1.0",4 "version": "1.2.1", 5 5 "type": "wordpress-plugin", 6 6 "license": "GPL-2.0+", -
jne-shipping-official/trunk/includes/class-jne-woocommerce-api.php
r3387194 r3411298 191 191 } 192 192 193 public function get_provinces()194 {195 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key();196 197 return $this->request('/v1/jne/provinces', [], 'GET', [198 'Authorization' => $access_key199 ]);200 }201 202 193 public function get_tariff_by_zipcode($destination_zipcode, $weight) 203 194 { … … 253 244 254 245 /** 246 * Get provinces 247 * @return array|WP_Error 248 */ 249 public function get_provinces() 250 { 251 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key(); 252 253 $response = $this->request('/v1/jne/provinces', [], 'GET', [ 254 'Authorization' => $access_key 255 ]); 256 257 if (is_wp_error($response)) { 258 return []; 259 } 260 261 return $response['data'] ?? []; 262 } 263 264 /** 265 * Get cities 266 * @param int $province_code 267 * @param int $page 268 * @param int $per_page 269 * @param string $search 270 * @return array|WP_Error 271 */ 272 public function get_cities($province_code, $page = 1, $per_page = 10, $search = '') 273 { 274 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key(); 275 276 $params = [ 277 'page' => $page, 278 'per_page' => $per_page, 279 'province_code' => $province_code 280 ]; 281 282 if (!empty($search)) { 283 $params['search'] = $search; 284 } 285 286 $query_string = '?' . http_build_query($params); 287 288 return $this->request('/v1/jne/cities' . $query_string, [], 'GET', [ 289 'Authorization' => $access_key 290 ]); 291 } 292 293 /** 294 * Get districts 295 * @param int $province_code 296 * @param string $city_name 297 * @param int $page 298 * @param int $per_page 299 * @param string $search 300 * @return array|WP_Error 301 */ 302 public function get_districts($province_code, $city_name, $page = 1, $per_page = 10, $search = '') 303 { 304 $access_key = Jneshof_Woocommerce_Configs::get_store_access_key(); 305 306 $params = [ 307 'page' => $page, 308 'per_page' => $per_page, 309 'province_code' => $province_code, 310 'city_name' => $city_name 311 ]; 312 313 if (!empty($search)) { 314 $params['search'] = $search; 315 } 316 317 $query_string = '?' . http_build_query($params); 318 319 return $this->request('/v1/jne/districts' . $query_string, [], 'GET', [ 320 'Authorization' => $access_key 321 ]); 322 } 323 324 /** 255 325 * Generate cnote 256 326 * @param array $data -
jne-shipping-official/trunk/jne-shipping-official.php
r3399074 r3411298 20 20 * Plugin Name: JNE Shipping Official 21 21 * Description: WordPress plugin integrated with WooCommerce for JNE shipping services 22 * Version: 1. 1.022 * Version: 1.2.1 23 23 * Author: PT. Tiki Jalur Nugraha Ekakurir 24 24 * Author URI: https://jne.co.id/ … … 48 48 * Rename this for your plugin and update it as you release new versions. 49 49 */ 50 define('JNESHOF_PLUGIN_VERSION', '1. 1.0');50 define('JNESHOF_PLUGIN_VERSION', '1.2.1'); 51 51 52 52 /** -
jne-shipping-official/trunk/public/class-jne-woocommerce-public.php
r3387194 r3411298 68 68 Jneshof_Checkout_Shipping_Insurance::get_instance(); 69 69 } 70 if (class_exists('Jneshof_Checkout_Shipping_Cost_Adjustment')) { 71 Jneshof_Checkout_Shipping_Cost_Adjustment::get_instance(); 72 } 70 73 if (class_exists('Jneshof_Admin_Generate_Cnote')) { 71 74 Jneshof_Admin_Generate_Cnote::get_instance(); … … 78 81 require_once plugin_dir_path(dirname(__FILE__)) . 'public/includes/jne-woocommerce-public-cod.php'; 79 82 require_once plugin_dir_path(dirname(__FILE__)) . 'public/includes/jne-woocommerce-public-insurance.php'; 83 require_once plugin_dir_path(dirname(__FILE__)) . 'public/includes/jne-woocommerce-public-shipping-cost-adjustment.php'; 80 84 } 81 85 -
jne-shipping-official/trunk/readme.txt
r3399074 r3411298 6 6 Tested up to: 6.8 7 7 Requires PHP: 7.4 8 Stable tag: 1. 1.08 Stable tag: 1.2.1 9 9 License: GPL-2.0+ 10 10 License URI: http://www.gnu.org/licenses/gpl-2.0.txt … … 90 90 91 91 == Changelog == 92 93 = 1.2.1 = 94 * Added validation to check if order has tracking number before requesting pickup 95 * Added validation to check if order has tracking number before generating shipping label (AWB) 96 * Improved error messages to guide users to generate CNote first when tracking number is missing 97 * Enhanced bulk AWB generation to skip orders without tracking numbers with clear error messages 98 99 = 1.2.0 = 100 * Added Shipping Cost Adjustments feature - Create and manage adjustment profiles to modify shipping costs 101 * Support for multiple adjustment types: Free Shipping, Add/Subtract Fixed Amount, Add/Subtract Percentage 102 * Flexible condition matching based on Services, Provinces, Cities, and Districts 103 * Date range support for time-limited adjustments 104 * Active/Inactive toggle for each adjustment profile 105 * Dual list box interface for selecting cities and districts (add/remove mechanism) 106 * Automatic application of adjustments as cart fees 107 * Adjustment rates are displayed as "Shipping Cost Discount" or "Shipping Cost Addition" in cart/checkout 92 108 93 109 = 1.1.0 =
Note: See TracChangeset
for help on using the changeset viewer.