init(); } public function init() { add_action('woocommerce_order_item_add_action_buttons', array($this, 'routeapp_custom_admin_button'), 10, 1); add_action('woocommerce_new_order_item', array($this, 'recalculate_route_fee'), 10, 1); add_action('woocommerce_add_order_tax', array($this, 'recalculate_route_fee'), 10, 1); add_action('woocommerce_saved_order_items', array($this, 'recalculate_route_fee'), 10, 1); add_action('woocommerce_delete_order_item', array($this, 'recalculate_route_fee'), 10, 1); } public static function get_route_public_instance(){ global $routeapp_public; return $routeapp_public; } public function routeapp_custom_admin_button($order) { if (!$this->can_add_fee($order)) { return false; } if ( is_admin() && in_array($order->get_status(), ['pending', 'on-hold', 'auto-draft']) ) { if ($this->has_route_fee_applied($order)) { echo ''; } else { echo ''; } } } private function routeapp_handle_admin_fee($order) { if (!$this->can_add_fee($order)) { return false; } $routeapp_public = self::get_route_public_instance(); //order doesn't have a hash, we use time to auto-generate one $cartRef = time(); $cartTotal = round($routeapp_public->get_cart_subtotal_with_only_shippable_items($order, 'order'), 2); $currency = get_woocommerce_currency(); $cartItems = $routeapp_public->get_cart_shippable_items($order, 'order'); $route_insurance_quote = $routeapp_public->routeapp_get_quote_from_api($cartRef, $cartTotal, $currency, $cartItems); $route_insurance_amount = false; //only add fee if the quote is covered by customer and has a valid amount if (isset($route_insurance_quote->premium->amount) && (isset($route_insurance_quote->payment_responsible->type)) && $route_insurance_quote->payment_responsible->type==$routeapp_public->get_allowed_quote_type()) { $route_insurance_amount = $route_insurance_quote->premium->amount; } if ($route_insurance_amount > 0) { $this->routeapp_create_fee($order, $route_insurance_amount); $order->calculate_totals(); if ($order->save()) { $acceptedOrderStatuses = get_option('routeapp_included_order_statuses') ? get_option('routeapp_included_order_statuses') : []; $acceptedCanceledStatuses = get_option('routeapp_cancel_order_statuses') ? get_option('routeapp_cancel_order_statuses') : []; if ( class_exists('Automattic\WooCommerce\Utilities\OrderUtil') && OrderUtil::custom_orders_table_usage_is_enabled() ) { // HPOS usage is enabled. $order->update_meta_data(self::ROUTE_CHARGE_POST_META, $route_insurance_amount ); $order->update_meta_data(self::ROUTE_PROTECTION_POST_META, true ); $order->update_meta_data('_routeapp_included_order_statuses', json_encode($acceptedOrderStatuses)); $order->update_meta_data( '_routeapp_cancel_order_statuses', json_encode($acceptedCanceledStatuses)); $order->save(); } else { // Traditional CPT-based orders are in use. update_post_meta( $order->get_id(), self::ROUTE_CHARGE_POST_META, $route_insurance_amount ); update_post_meta( $order->get_id(), self::ROUTE_PROTECTION_POST_META, true ); update_post_meta( $order->get_id(), '_routeapp_included_order_statuses', json_encode($acceptedOrderStatuses)); update_post_meta( $order->get_id(), '_routeapp_cancel_order_statuses', json_encode($acceptedCanceledStatuses)); } return true; } }else { if ($this->has_route_fee_applied($order)) { $this->routeapp_remove_route_fee($order); } } return false; } private function routeapp_create_fee($order, $fee_amount) { $routeapp_public = self::get_route_public_instance(); if (!$this->has_route_fee_applied($order)) { $item_fee = new WC_Order_Item_Fee(); $item_fee->set_name( Routeapp_Public::ROUTE_LABEL ); $item_fee->set_tax_class( $routeapp_public->routeapp_get_taxable_class() ); $item_fee->set_tax_status( $routeapp_public->routeapp_get_fee_taxable() ? 'taxable' : 'none' ); $item_fee->set_amount( $fee_amount ); $item_fee->set_total( $fee_amount ); $order->add_item( $item_fee ); } else { $fees = $this->get_route_fees($order); foreach($fees as $fee_id => $fee) { if ($fee) { $fee->set_amount($fee_amount); $fee->set_total($fee_amount); $fee->save(); } } } } public function routeapp_add_admin_fee() { check_ajax_referer( 'order-item', 'security' ); if (!isset($_POST) || !$_POST['order_id']) { wp_send_json_error('its missing order id on the request'); return; } $order_id = isset($_POST['order_id']) ? $_POST['order_id'] : 0; $order = wc_get_order( $order_id ); $response = $this->routeapp_handle_admin_fee($order); if ($response) { wp_send_json_success( 'order updated!' ); return; } wp_send_json_error('error while adding route fee to the order'); } function routeapp_remove_admin_fee() { check_ajax_referer( 'order-item', 'security' ); if (!isset($_POST) || !$_POST['order_id']) { wp_send_json_error('its missing order id on the request'); return; } $order_id = isset($_POST['order_id']) ? $_POST['order_id'] : 0; $order = wc_get_order( $order_id ); if ($this->has_route_fee_applied($order)) { $this->routeapp_remove_route_fee($order); } wp_send_json_success('route fee removed from the order'); } private function routeapp_remove_route_fee($order) { $fees = $this->get_route_fees($order); foreach($fees as $fee_id => $fee) { if ($fee) { wc_delete_order_item($fee_id); } } delete_post_meta( $order->get_id(), self::ROUTE_CHARGE_POST_META ); delete_post_meta( $order->get_id(), self::ROUTE_PROTECTION_POST_META ); } public function recalculate_route_fee($order_id) { $order = wc_get_order( $order_id ); if ($this->has_route_fee_applied($order)) { $this->routeapp_handle_admin_fee($order); } } private function get_quote_from_api($order_total) { $response = Routeapp_API_Client::getInstance()->get_quote($order_total, get_woocommerce_currency()); if (is_wp_error($response)) { return false; } else { if ($response['response']['code'] == 401) { return false; } $price_data = json_decode($response['body']); return $price_data; } } private function get_route_fees($order) { if (!$order) { return []; } $fees = $order->get_fees(); $route_fees = []; foreach($fees as $fee_id => $fee) { if($fee['name'] == Routeapp_Public::ROUTE_LABEL) { $route_fees[$fee_id] = $fee; } } return $route_fees; } public function can_add_fee($order) { return $order && count($order->get_items()) > 0 && $order->get_status() == 'auto-draft'; } private function has_route_fee_applied($order) { $routeFees = $this->get_route_fees($order); if (is_array($routeFees) || $routeFees instanceof Countable) { return count($routeFees) > 0; } return false; } }