PluginProbe
Route ‑ Shipping Protection / 2.4.18
Route ‑ Shipping Protection v2.4.18
2.4.19 2.4.18 2.4.17 2.4.16 2.4.15 2.4.14 2.4.13 2.4.12 2.4.11 2.4.10 2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.2.4 2.2.5 2.2.6 2.2.8 2.2.9 2.3.0 2.3.1 All 153 releases
← All changes | includes/class-routeapp-admin-route-fee.php +151 -38 2.4.9 → 2.4.18 View file →
@@ -6,8 +6,15 @@
6 6
7 7 const ROUTE_CHARGE_POST_META = '_routeapp_route_charge';
8 8 const ROUTE_PROTECTION_POST_META = '_routeapp_route_protection';
9 9
10 + /**
11 + * Per-request quote cache keyed by admin cart ref.
12 + *
13 + * @var array<string, object|false>
14 + */
15 + private $admin_order_quote_cache = array();
16 +
10 17 public function __construct()
11 18 {
12 19 if (!is_admin()) {
13 20 return false;
@@ -30,21 +37,120 @@
30 37 }
31 38
32 39 public function routeapp_custom_admin_button($order)
33 40 {
34 - if (!$this->can_add_fee($order)) {
41 + echo $this->get_route_fee_button_html($order);
42 + }
43 +
44 + public function get_route_fee_button_html($order)
45 + {
46 + if (!$this->can_show_route_fee_buttons($order)) {
47 + return '';
48 + }
49 +
50 + if ($this->has_route_fee_applied($order)) {
51 + return '<button type="button" id="remove-route-fee" class="button generate-items">' . esc_html__( 'Remove Route Fee', 'routeapp' ) . '</button>';
52 + }
53 +
54 + if ($this->is_order_eligible_for_route_coverage($order)) {
55 + return '<button type="button" id="add-route-fee" class="button generate-items">' . esc_html__( 'Add Route Fee', 'routeapp' ) . '</button>';
56 + }
57 +
58 + return '';
59 + }
60 +
61 + public function routeapp_refresh_admin_fee_button()
62 + {
63 + check_ajax_referer( 'order-item', 'security' );
64 +
65 + if (!isset($_POST['order_id'])) {
66 + wp_send_json_error('Missing order_id in the request.');
67 + return;
68 + }
69 +
70 + $order = wc_get_order(absint($_POST['order_id']));
71 + if (!$order) {
72 + wp_send_json_error('Invalid order_id.');
73 + return;
74 + }
75 +
76 + wp_send_json_success(array(
77 + 'html' => $this->get_route_fee_button_html($order),
78 + ));
79 + }
80 +
81 + private function get_admin_order_cart_ref($order, $cart_total, $cart_items)
82 + {
83 + $items_hash = substr(md5(wp_json_encode($cart_items)), 0, 8);
84 +
85 + return 'admin-' . $order->get_id() . '-' . $cart_total . '-' . $items_hash;
86 + }
87 +
88 + private function get_admin_order_quote_context($order)
89 + {
90 + $routeapp_public = self::get_route_public_instance();
91 + $cart_total = round($routeapp_public->get_cart_subtotal_with_only_shippable_items($order, 'order'), 2);
92 + $cart_items = $routeapp_public->get_cart_shippable_items($order, 'order');
93 +
94 + return array(
95 + 'total' => $cart_total,
96 + 'items' => $cart_items,
97 + 'ref' => $this->get_admin_order_cart_ref($order, $cart_total, $cart_items),
98 + 'currency' => get_woocommerce_currency(),
99 + 'public' => $routeapp_public,
100 + );
101 + }
102 +
103 + private function fetch_admin_order_quote($order)
104 + {
105 + $context = $this->get_admin_order_quote_context($order);
106 +
107 + if ($context['total'] <= 0) {
35 108 return false;
36 109 }
37 110
38 - if ( is_admin() && in_array($order->get_status(), ['pending', 'on-hold', 'auto-draft']) ) {
39 - if ($this->has_route_fee_applied($order)) {
40 - echo '<button type="button" id="remove-route-fee" class="button generate-items">' . __( 'Remove Route Fee') . '</button>';
41 - } else {
42 - echo '<button type="button" id="add-route-fee" class="button generate-items">' . __( 'Add Route Fee') . '</button>';
43 - }
111 + if (array_key_exists($context['ref'], $this->admin_order_quote_cache)) {
112 + return $this->admin_order_quote_cache[$context['ref']];
44 113 }
114 +
115 + $quote = $context['public']->routeapp_get_quote_from_api(
116 + $context['ref'],
117 + $context['total'],
118 + $context['currency'],
119 + $context['items']
120 + );
121 +
122 + $this->admin_order_quote_cache[$context['ref']] = $quote;
123 +
124 + return $quote;
45 125 }
46 126
127 + public function is_order_eligible_for_route_coverage($order)
128 + {
129 + if (!$order) {
130 + return false;
131 + }
132 +
133 + $routeapp_public = self::get_route_public_instance();
134 + $route_insurance_quote = $this->fetch_admin_order_quote($order);
135 +
136 + return $this->is_quote_eligible_for_customer_coverage($route_insurance_quote, $routeapp_public);
137 + }
138 +
139 + private function is_quote_eligible_for_customer_coverage($route_insurance_quote, $routeapp_public)
140 + {
141 + if (!$route_insurance_quote) {
142 + return false;
143 + }
144 +
145 + if (!isset($route_insurance_quote->premium->amount) || $route_insurance_quote->premium->amount <= 0) {
146 + return false;
147 + }
148 +
149 + return isset($route_insurance_quote->payment_responsible->type)
150 + && $route_insurance_quote->payment_responsible->type === $routeapp_public->get_allowed_quote_type();
151 + }
152 +
47 153 private function routeapp_handle_admin_fee($order)
48 154 {
49 155 if (!$this->can_add_fee($order)) {
50 156 return false;
@@ -49,19 +155,12 @@
49 155 if (!$this->can_add_fee($order)) {
50 156 return false;
51 157 }
52 158 $routeapp_public = self::get_route_public_instance();
53 - //order doesn't have a hash, we use time to auto-generate one
54 - $cartRef = time();
55 - $cartTotal = round($routeapp_public->get_cart_subtotal_with_only_shippable_items($order, 'order'), 2);
56 - $currency = get_woocommerce_currency();
57 - $cartItems = $routeapp_public->get_cart_shippable_items($order, 'order');
58 - $route_insurance_quote = $routeapp_public->routeapp_get_quote_from_api($cartRef, $cartTotal, $currency, $cartItems);
159 + $route_insurance_quote = $this->fetch_admin_order_quote($order);
59 160
60 161 $route_insurance_amount = false;
61 - //only add fee if the quote is covered by customer and has a valid amount
62 - if (isset($route_insurance_quote->premium->amount) &&
63 - (isset($route_insurance_quote->payment_responsible->type)) && $route_insurance_quote->payment_responsible->type==$routeapp_public->get_allowed_quote_type()) {
162 + if ($this->is_quote_eligible_for_customer_coverage($route_insurance_quote, $routeapp_public)) {
64 163 $route_insurance_amount = $route_insurance_quote->premium->amount;
65 164 }
66 165 if ($route_insurance_amount > 0) {
67 166 $this->routeapp_create_fee($order, $route_insurance_amount);
@@ -91,11 +190,13 @@
91 190
92 191 }
93 192 return true;
94 193 }
95 - }else {
194 + } else {
96 195 if ($this->has_route_fee_applied($order)) {
97 196 $this->routeapp_remove_route_fee($order);
197 + $order->calculate_totals();
198 + $order->save();
98 199 }
99 200 }
100 201
101 202 return false;
@@ -109,8 +210,9 @@
109 210 $item_fee->set_tax_class( $routeapp_public->routeapp_get_taxable_class() );
110 211 $item_fee->set_tax_status( $routeapp_public->routeapp_get_fee_taxable() ? 'taxable' : 'none' );
111 212 $item_fee->set_amount( $fee_amount );
112 213 $item_fee->set_total( $fee_amount );
214 + Routeapp_Public::routeapp_mark_protection_fee_item( $item_fee );
113 215 $order->add_item( $item_fee );
114 216 } else {
115 217 $fees = $this->get_route_fees($order);
116 218 foreach($fees as $fee_id => $fee) {
@@ -116,8 +218,9 @@
116 218 foreach($fees as $fee_id => $fee) {
117 219 if ($fee) {
118 220 $fee->set_amount($fee_amount);
119 221 $fee->set_total($fee_amount);
222 + Routeapp_Public::routeapp_mark_protection_fee_item( $fee );
120 223 $fee->save();
121 224 }
122 225 }
123 226 }
@@ -127,14 +230,18 @@
127 230 {
128 231 check_ajax_referer( 'order-item', 'security' );
129 232
130 233 if (!isset($_POST) || !$_POST['order_id']) {
131 - wp_send_json_error('its missing order id on the request');
234 + wp_send_json_error('Missing order_id in the request.');
132 235 return;
133 236 }
134 237
135 238 $order_id = isset($_POST['order_id']) ? $_POST['order_id'] : 0;
136 239 $order = wc_get_order( $order_id );
240 + if (!$order) {
241 + wp_send_json_error('Invalid order_id.');
242 + return;
243 + }
137 244
138 245 $response = $this->routeapp_handle_admin_fee($order);
139 246
140 247 if ($response) {
@@ -149,17 +256,23 @@
149 256 {
150 257 check_ajax_referer( 'order-item', 'security' );
151 258
152 259 if (!isset($_POST) || !$_POST['order_id']) {
153 - wp_send_json_error('its missing order id on the request');
260 + wp_send_json_error('Missing order_id in the request.');
154 261 return;
155 262 }
156 263
157 264 $order_id = isset($_POST['order_id']) ? $_POST['order_id'] : 0;
158 265 $order = wc_get_order( $order_id );
266 + if (!$order) {
267 + wp_send_json_error('Invalid order_id.');
268 + return;
269 + }
159 270
160 271 if ($this->has_route_fee_applied($order)) {
161 272 $this->routeapp_remove_route_fee($order);
273 + $order->calculate_totals();
274 + $order->save();
162 275 }
163 276
164 277 wp_send_json_success('route fee removed from the order');
165 278 }
@@ -172,10 +285,17 @@
172 285 if ($fee) {
173 286 wc_delete_order_item($fee_id);
174 287 }
175 288 }
176 - delete_post_meta( $order->get_id(), self::ROUTE_CHARGE_POST_META );
177 - delete_post_meta( $order->get_id(), self::ROUTE_PROTECTION_POST_META );
289 +
290 + if ( class_exists('Automattic\WooCommerce\Utilities\OrderUtil')
291 + && OrderUtil::custom_orders_table_usage_is_enabled() ) {
292 + $order->delete_meta_data(self::ROUTE_CHARGE_POST_META);
293 + $order->delete_meta_data(self::ROUTE_PROTECTION_POST_META);
294 + } else {
295 + delete_post_meta( $order->get_id(), self::ROUTE_CHARGE_POST_META );
296 + delete_post_meta( $order->get_id(), self::ROUTE_PROTECTION_POST_META );
297 + }
178 298 }
179 299
180 300 public function recalculate_route_fee($order_id)
181 301 {
@@ -185,23 +305,8 @@
185 305 $this->routeapp_handle_admin_fee($order);
186 306 }
187 307 }
188 308
189 - private function get_quote_from_api($order_total)
190 - {
191 - $response = Routeapp_API_Client::getInstance()->get_quote($order_total, get_woocommerce_currency());
192 -
193 - if (is_wp_error($response)) {
194 - return false;
195 - } else {
196 - if ($response['response']['code'] == 401) {
197 - return false;
198 - }
199 - $price_data = json_decode($response['body']);
200 - return $price_data;
201 - }
202 - }
203 -
204 309 private function get_route_fees($order)
205 310 {
206 311 if (!$order) {
207 312 return [];
@@ -209,9 +314,9 @@
209 314
210 315 $fees = $order->get_fees();
211 316 $route_fees = [];
212 317 foreach($fees as $fee_id => $fee) {
213 - if($fee['name'] == Routeapp_Public::ROUTE_LABEL) {
318 + if (Routeapp_Public::routeapp_is_route_protection_fee($fee)) {
214 319 $route_fees[$fee_id] = $fee;
215 320 }
216 321 }
217 322 return $route_fees;
@@ -216,11 +321,19 @@
216 321 }
217 322 return $route_fees;
218 323 }
219 324
325 + public function can_show_route_fee_buttons($order)
326 + {
327 + return $order
328 + && count($order->get_items()) > 0
329 + && is_admin()
330 + && in_array($order->get_status(), array('pending', 'on-hold', 'auto-draft'), true);
331 + }
332 +
220 333 public function can_add_fee($order)
221 334 {
222 - return $order && count($order->get_items()) > 0 && $order->get_status() == 'auto-draft';
335 + return $this->can_show_route_fee_buttons($order);
223 336 }
224 337
225 338 private function has_route_fee_applied($order)
226 339 {