WP_REST_Server::READABLE, 'callback' => array( $this, 'get_settings' ), 'permission_callback' => array( $this, 'check_permission' ), ) ); // Toggle tax calculation register_rest_route( $namespace, '/settings/tax/toggle', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'toggle_tax' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'enabled' => array( 'required' => true, 'type' => 'boolean', 'sanitize_callback' => 'rest_sanitize_boolean', ), ), ) ); // Get suggested tax rates based on selling locations register_rest_route( $namespace, '/settings/tax/suggested', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_suggested_rates' ), 'permission_callback' => array( $this, 'check_permission' ), ) ); // Create tax rate register_rest_route( $namespace, '/settings/tax/rates', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'create_rate' ), 'permission_callback' => array( $this, 'check_permission' ), ) ); // Update tax rate register_rest_route( $namespace, '/settings/tax/rates/(?P\d+)', array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_rate' ), 'permission_callback' => array( $this, 'check_permission' ), ) ); // Delete tax rate register_rest_route( $namespace, '/settings/tax/rates/(?P\d+)', array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_rate' ), 'permission_callback' => array( $this, 'check_permission' ), ) ); } /** * Check permission */ public function check_permission() { return current_user_can( 'manage_woocommerce' ); } /** * Get tax settings */ public function get_settings( WP_REST_Request $request ) { try { $settings = array( 'calc_taxes' => get_option( 'woocommerce_calc_taxes', 'no' ), 'prices_include_tax' => get_option( 'woocommerce_prices_include_tax', 'no' ), 'tax_based_on' => get_option( 'woocommerce_tax_based_on', 'shipping' ), 'tax_display_shop' => get_option( 'woocommerce_tax_display_shop', 'excl' ), 'tax_display_cart' => get_option( 'woocommerce_tax_display_cart', 'excl' ), 'standard_rates' => $this->get_tax_rates( 'standard' ), 'reduced_rates' => $this->get_tax_rates( 'reduced-rate' ), 'zero_rates' => $this->get_tax_rates( 'zero-rate' ), ); return new WP_REST_Response( $settings, 200 ); } catch ( \Exception $e ) { return new WP_REST_Response( array( 'error' => 'fetch_failed', 'message' => $e->getMessage(), ), 500 ); } } /** * Toggle tax calculation */ public function toggle_tax( WP_REST_Request $request ) { try { $enabled = $request->get_param( 'enabled' ); $value = $enabled ? 'yes' : 'no'; update_option( 'woocommerce_calc_taxes', $value ); // Clear WooCommerce cache \WC_Cache_Helper::invalidate_cache_group( 'taxes' ); \WC_Cache_Helper::get_transient_version( 'shipping', true ); return new WP_REST_Response( array( 'success' => true, 'enabled' => $enabled, 'message' => $enabled ? __( 'Tax calculation enabled', 'woonoow' ) : __( 'Tax calculation disabled', 'woonoow' ), ), 200 ); } catch ( \Exception $e ) { return new WP_REST_Response( array( 'error' => 'update_failed', 'message' => $e->getMessage(), ), 500 ); } } /** * Get tax rates for a specific class */ private function get_tax_rates( $tax_class ) { global $wpdb; // For 'standard' class, match both empty string and 'standard' if ( $tax_class === 'standard' ) { $rates = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_class = '' OR tax_rate_class = 'standard' ORDER BY tax_rate_order ASC" ); } else { $rates = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_class = %s ORDER BY tax_rate_order ASC", $tax_class ) ); } $formatted_rates = array(); foreach ( $rates as $rate ) { $formatted_rates[] = array( 'id' => $rate->tax_rate_id, 'country' => $rate->tax_rate_country, 'state' => $rate->tax_rate_state, 'rate' => $rate->tax_rate, 'name' => $rate->tax_rate_name, 'priority' => $rate->tax_rate_priority, 'compound' => $rate->tax_rate_compound, 'shipping' => $rate->tax_rate_shipping, ); } return $formatted_rates; } /** * Get suggested tax rates based on WooCommerce selling locations */ public function get_suggested_rates( WP_REST_Request $request ) { try { // Predefined tax rates by country $predefined_rates = array( 'ID' => array( 'country' => 'Indonesia', 'rate' => 11, 'name' => 'PPN (VAT)' ), 'MY' => array( 'country' => 'Malaysia', 'rate' => 6, 'name' => 'SST' ), 'SG' => array( 'country' => 'Singapore', 'rate' => 9, 'name' => 'GST' ), 'TH' => array( 'country' => 'Thailand', 'rate' => 7, 'name' => 'VAT' ), 'PH' => array( 'country' => 'Philippines', 'rate' => 12, 'name' => 'VAT' ), 'VN' => array( 'country' => 'Vietnam', 'rate' => 10, 'name' => 'VAT' ), 'AU' => array( 'country' => 'Australia', 'rate' => 10, 'name' => 'GST' ), 'NZ' => array( 'country' => 'New Zealand', 'rate' => 15, 'name' => 'GST' ), 'GB' => array( 'country' => 'United Kingdom', 'rate' => 20, 'name' => 'VAT' ), 'DE' => array( 'country' => 'Germany', 'rate' => 19, 'name' => 'VAT' ), 'FR' => array( 'country' => 'France', 'rate' => 20, 'name' => 'VAT' ), 'IT' => array( 'country' => 'Italy', 'rate' => 22, 'name' => 'VAT' ), 'ES' => array( 'country' => 'Spain', 'rate' => 21, 'name' => 'VAT' ), 'CA' => array( 'country' => 'Canada', 'rate' => 5, 'name' => 'GST' ), ); // Get WooCommerce selling locations $selling_locations = get_option( 'woocommerce_allowed_countries', 'all' ); $suggested = array(); if ( $selling_locations === 'specific' ) { // User selected specific countries $countries = get_option( 'woocommerce_specific_allowed_countries', array() ); foreach ( $countries as $country_code ) { if ( isset( $predefined_rates[ $country_code ] ) ) { $suggested[] = array_merge( array( 'code' => $country_code ), $predefined_rates[ $country_code ] ); } } } else { // Sell to all countries - suggest store base country $store_country = get_option( 'woocommerce_default_country', '' ); $country_code = substr( $store_country, 0, 2 ); // Extract country code (e.g., 'ID' from 'ID:JB') if ( isset( $predefined_rates[ $country_code ] ) ) { $suggested[] = array_merge( array( 'code' => $country_code ), $predefined_rates[ $country_code ] ); } } return new WP_REST_Response( array( 'suggested' => $suggested, 'all_rates' => $predefined_rates, ), 200 ); } catch ( \Exception $e ) { return new WP_REST_Response( array( 'error' => 'fetch_failed', 'message' => $e->getMessage(), ), 500 ); } } /** * Create tax rate */ public function create_rate( WP_REST_Request $request ) { try { global $wpdb; $country = $request->get_param( 'country' ); $state = $request->get_param( 'state' ) ?? ''; $rate = $request->get_param( 'rate' ); $name = $request->get_param( 'name' ); $tax_class = $request->get_param( 'tax_class' ) ?? ''; $priority = $request->get_param( 'priority' ) ?? 1; $compound = $request->get_param( 'compound' ) ?? 0; $shipping = $request->get_param( 'shipping' ) ?? 1; $wpdb->insert( $wpdb->prefix . 'woocommerce_tax_rates', array( 'tax_rate_country' => $country, 'tax_rate_state' => $state, 'tax_rate' => $rate, 'tax_rate_name' => $name, 'tax_rate_priority' => $priority, 'tax_rate_compound' => $compound, 'tax_rate_shipping' => $shipping, 'tax_rate_order' => 0, 'tax_rate_class' => $tax_class, ), array( '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%d', '%s' ) ); $rate_id = $wpdb->insert_id; // Clear cache \WC_Cache_Helper::invalidate_cache_group( 'taxes' ); return new WP_REST_Response( array( 'success' => true, 'id' => $rate_id, 'message' => __( 'Tax rate created', 'woonoow' ), ), 201 ); } catch ( \Exception $e ) { return new WP_REST_Response( array( 'error' => 'create_failed', 'message' => $e->getMessage(), ), 500 ); } } /** * Update tax rate */ public function update_rate( WP_REST_Request $request ) { try { global $wpdb; $rate_id = $request->get_param( 'id' ); $country = $request->get_param( 'country' ); $state = $request->get_param( 'state' ) ?? ''; $rate = $request->get_param( 'rate' ); $name = $request->get_param( 'name' ); $tax_class = $request->get_param( 'tax_class' ) ?? ''; $priority = $request->get_param( 'priority' ) ?? 1; $compound = $request->get_param( 'compound' ) ?? 0; $shipping = $request->get_param( 'shipping' ) ?? 1; $wpdb->update( $wpdb->prefix . 'woocommerce_tax_rates', array( 'tax_rate_country' => $country, 'tax_rate_state' => $state, 'tax_rate' => $rate, 'tax_rate_name' => $name, 'tax_rate_priority' => $priority, 'tax_rate_compound' => $compound, 'tax_rate_shipping' => $shipping, 'tax_rate_class' => $tax_class, ), array( 'tax_rate_id' => $rate_id ), array( '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%s' ), array( '%d' ) ); // Clear cache \WC_Cache_Helper::invalidate_cache_group( 'taxes' ); return new WP_REST_Response( array( 'success' => true, 'message' => __( 'Tax rate updated', 'woonoow' ), ), 200 ); } catch ( \Exception $e ) { return new WP_REST_Response( array( 'error' => 'update_failed', 'message' => $e->getMessage(), ), 500 ); } } /** * Delete tax rate */ public function delete_rate( WP_REST_Request $request ) { try { global $wpdb; $rate_id = $request->get_param( 'id' ); $wpdb->delete( $wpdb->prefix . 'woocommerce_tax_rates', array( 'tax_rate_id' => $rate_id ), array( '%d' ) ); // Also delete rate locations $wpdb->delete( $wpdb->prefix . 'woocommerce_tax_rate_locations', array( 'tax_rate_id' => $rate_id ), array( '%d' ) ); // Clear cache \WC_Cache_Helper::invalidate_cache_group( 'taxes' ); return new WP_REST_Response( array( 'success' => true, 'message' => __( 'Tax rate deleted', 'woonoow' ), ), 200 ); } catch ( \Exception $e ) { return new WP_REST_Response( array( 'error' => 'delete_failed', 'message' => $e->getMessage(), ), 500 ); } } }