/**
  * CallSetExpressCheckout
  *
  * Makes a request to PayPal's SetExpressCheckout API
  * to setup the checkout and obtain a token.
  *
  * @paymentAmount (double) Total payment amount of the order.
  * @returnURL (string) URL for PayPal to send the buyer to after review and continue from PayPal.
  * @cancelURL (string) URL for PayPal to send the buyer to if they cancel the payment.
  */
 function CallSetExpressCheckout($paymentAmount, $returnURL, $cancelURL, $usePayPalCredit = false, $posted)
 {
     /*
      * Display message to user if session has expired.
      */
     if (sizeof(WC()->cart->get_cart()) == 0) {
         $ms = sprintf(__('Sorry, your session has expired. <a href=%s>Return to homepage &rarr;</a>', 'paypal-for-woocommerce'), '"' . home_url() . '"');
         $set_ec_message = apply_filters('angelleye_set_ec_message', $ms);
         wc_add_notice($set_ec_message, "error");
     }
     /*
      * Check if the PayPal class has already been established.
      */
     if (!class_exists('Angelleye_PayPal')) {
         require_once 'lib/angelleye/paypal-php-library/includes/paypal.class.php';
     }
     /*
      * Create PayPal object.
      */
     $PayPalConfig = array('Sandbox' => $this->testmode == 'yes' ? TRUE : FALSE, 'APIUsername' => $this->api_username, 'APIPassword' => $this->api_password, 'APISignature' => $this->api_signature);
     $PayPal = new Angelleye_PayPal($PayPalConfig);
     /**
      * Prepare PayPal request data.
      */
     /**
      * If Gift Wrap options are enabled, then MAXAMT is required
      * in SetExpressCheckout.
      *
      * https://github.com/angelleye/paypal-woocommerce/issues/142
      */
     if ($this->gift_wrap_enabled == 'yes') {
         $maxAmount = $paymentAmount * 2;
         $maxAmount = $maxAmount + $this->gift_wrap_amount;
         $maxAmount = number_format($maxAmount, 2, '.', '');
     } else {
         $maxAmount = '';
     }
     $SECFields = array('token' => '', 'maxamt' => $maxAmount, 'returnurl' => urldecode($returnURL), 'cancelurl' => urldecode($cancelURL), 'callback' => '', 'callbacktimeout' => '', 'callbackversion' => '', 'reqconfirmshipping' => '', 'noshipping' => '', 'allownote' => '', 'addroverride' => '', 'localecode' => $this->use_wp_locale_code == 'yes' && get_locale() != '' ? get_locale() : '', 'pagestyle' => '', 'hdrimg' => $this->checkout_logo_hdrimg, 'logourl' => $this->checkout_logo, 'hdrbordercolor' => '', 'hdrbackcolor' => '', 'payflowcolor' => '', 'skipdetails' => $this->skip_final_review == 'yes' ? '1' : '0', 'email' => '', 'channeltype' => '', 'giropaysuccessurl' => '', 'giropaycancelurl' => '', 'banktxnpendingurl' => '', 'brandname' => $this->brand_name, 'customerservicenumber' => $this->customer_service_number, 'buyeremailoptionenable' => '', 'surveyquestion' => '', 'surveyenable' => '', 'totaltype' => '', 'notetobuyer' => '', 'buyerid' => '', 'buyerusername' => '', 'buyerregistrationdate' => '', 'allowpushfunding' => '', 'taxidtype' => '', 'taxid' => '');
     /**
      * If Gift Wrap options are enabled, add them to SEC
      */
     if (strtolower($this->gift_wrap_enabled) == 'yes') {
         $SECFields['giftwrapenable'] = '1';
         // Enable gift wrap widget on the PayPal Review page.  Allowable values are 0 and 1.
         $SECFields['giftmessageenable'] = $this->gift_message_enabled ? '1' : '';
         // Enable gift message widget on the PayPal Review page. Allowable values are 0 and 1
         $SECFields['giftreceiptenable'] = $this->gift_receipt_enabled ? '1' : '';
         // Enable gift receipt widget on the PayPal Review page. Allowable values are 0 and 1
         $SECFields['giftwrapname'] = $this->gift_wrap_name;
         // Label for the gift wrap option such as "Box with ribbon".  25 char max.
         $SECFields['giftwrapamount'] = $this->gift_wrap_amount;
         // Amount charged for gift-wrap service.
     }
     /**
      * If PayPal Credit is being used, override the necessary parameters
      */
     if ($usePayPalCredit) {
         $SECFields['solutiontype'] = 'Sole';
         $SECFields['landingpage'] = 'Billing';
         $SECFields['userselectedfundingsource'] = 'BML';
     } elseif (strtolower($this->paypal_account_optional) == 'yes' && strtolower($this->landing_page) == 'billing') {
         $SECFields['solutiontype'] = 'Sole';
         $SECFields['landingpage'] = 'Billing';
         $SECFields['userselectedfundingsource'] = 'CreditCard';
     } elseif (strtolower($this->paypal_account_optional) == 'yes' && strtolower($this->landing_page) == 'login') {
         $SECFields['solutiontype'] = 'Sole';
         $SECFields['landingpage'] = 'Login';
     }
     // Basic array of survey choices.  Nothing but the values should go in here.
     $SurveyChoices = array('Choice 1', 'Choice2', 'Choice3', 'etc');
     /*
      * Get tax amount.
      */
     if (get_option('woocommerce_prices_include_tax') == 'yes') {
         $shipping = WC()->cart->shipping_total + WC()->cart->shipping_tax_total;
         $tax = '0.00';
     } else {
         $shipping = WC()->cart->shipping_total;
         $tax = WC()->cart->get_taxes_total();
     }
     if ('yes' === get_option('woocommerce_calc_taxes') && 'yes' === get_option('woocommerce_prices_include_tax')) {
         $tax = wc_round_tax_total(WC()->cart->tax_total + WC()->cart->shipping_tax_total);
     }
     $Payments = array();
     $Payment = array('amt' => number_format(WC()->cart->total, 2, '.', ''), 'currencycode' => get_woocommerce_currency(), 'shippingamt' => number_format($shipping, 2, '.', ''), 'shippingdiscamt' => '', 'insuranceamt' => '', 'insuranceoptionoffered' => '', 'handlingamt' => '', 'taxamt' => number_format($tax, 2, '.', ''), 'desc' => '', 'custom' => '', 'invnum' => '', 'notifyurl' => '', 'shiptoname' => '', 'shiptostreet' => '', 'shiptostreet2' => '', 'shiptocity' => '', 'shiptostate' => '', 'shiptozip' => '', 'shiptocountrycode' => '', 'shiptophonenum' => '', 'notetext' => '', 'allowedpaymentmethod' => '', 'paymentaction' => $this->payment_action == 'Authorization' ? 'Authorization' : 'Sale', 'paymentrequestid' => '', 'sellerpaypalaccountid' => '');
     /**
      * If checkout like regular payment
      */
     if (!empty($posted) && WC()->cart->needs_shipping()) {
         $SECFields['addroverride'] = 1;
         if (@$posted['ship_to_different_address']) {
             $Payment['shiptoname'] = $posted['shipping_first_name'] . ' ' . $posted['shipping_last_name'];
             $Payment['shiptostreet'] = $posted['shipping_address_1'];
             $Payment['shiptostreet2'] = @$posted['shipping_address_2'];
             $Payment['shiptocity'] = @$posted['shipping_city'];
             $Payment['shiptostate'] = @$posted['shipping_state'];
             $Payment['shiptozip'] = @$posted['shipping_postcode'];
             $Payment['shiptocountrycode'] = @$posted['shipping_country'];
             $Payment['shiptophonenum'] = @$posted['shipping_phone'];
         } else {
             $Payment['shiptoname'] = $posted['billing_first_name'] . ' ' . $posted['billing_last_name'];
             $Payment['shiptostreet'] = $posted['billing_address_1'];
             $Payment['shiptostreet2'] = @$posted['billing_address_2'];
             $Payment['shiptocity'] = @$posted['billing_city'];
             $Payment['shiptostate'] = @$posted['billing_state'];
             $Payment['shiptozip'] = @$posted['billing_postcode'];
             $Payment['shiptocountrycode'] = @$posted['billing_country'];
             $Payment['shiptophonenum'] = @$posted['billing_phone'];
         }
     }
     $PaymentOrderItems = array();
     $ctr = $total_items = $total_discount = $total_tax = $order_total = 0;
     foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
         /*
          * Get product data from WooCommerce
          */
         $_product = $values['data'];
         $qty = absint($values['quantity']);
         $sku = $_product->get_sku();
         $values['name'] = html_entity_decode($_product->get_title(), ENT_NOQUOTES, 'UTF-8');
         /*
          * Append variation data to name.
          */
         if ($_product->product_type == 'variation') {
             $meta = WC()->cart->get_item_data($values, true);
             if (empty($sku)) {
                 $sku = $_product->parent->get_sku();
             }
             if (!empty($meta)) {
                 $values['name'] .= " - " . str_replace(", \n", " - ", $meta);
             }
         }
         $quantity = absint($values['quantity']);
         $Item = array('name' => $values['name'], 'desc' => '', 'amt' => round($values['line_subtotal'] / $quantity, 2), 'number' => $sku, 'qty' => $quantity, 'taxamt' => '', 'itemurl' => '', 'itemcategory' => '', 'itemweightvalue' => '', 'itemweightunit' => '', 'itemheightvalue' => '', 'itemheightunit' => '', 'itemwidthvalue' => '', 'itemwidthunit' => '', 'itemlengthvalue' => '', 'itemlengthunit' => '', 'ebayitemnumber' => '', 'ebayitemauctiontxnid' => '', 'ebayitemorderid' => '', 'ebayitemcartid' => '');
         array_push($PaymentOrderItems, $Item);
         $total_items += round($values['line_subtotal'] / $quantity, 2) * $quantity;
         $ctr++;
     }
     /**
      * Add custom Woo cart fees as line items
      */
     foreach (WC()->cart->get_fees() as $fee) {
         $Item = array('name' => $fee->name, 'desc' => '', 'amt' => number_format($fee->amount, 2, '.', ''), 'number' => $fee->id, 'qty' => 1, 'taxamt' => '', 'itemurl' => '', 'itemcategory' => '', 'itemweightvalue' => '', 'itemweightunit' => '', 'itemheightvalue' => '', 'itemheightunit' => '', 'itemwidthvalue' => '', 'itemwidthunit' => '', 'itemlengthvalue' => '', 'itemlengthunit' => '', 'ebayitemnumber' => '', 'ebayitemauctiontxnid' => '', 'ebayitemorderid' => '', 'ebayitemcartid' => '');
         array_push($PaymentOrderItems, $Item);
         $total_items += $fee->amount * $Item['qty'];
         $ctr++;
     }
     /*
      * Get discount(s)
      */
     if (WC()->cart->get_cart_discount_total() > 0) {
         foreach (WC()->cart->get_coupons('cart') as $code => $coupon) {
             $Item = array('name' => 'Cart Discount', 'number' => $code, 'qty' => '1', 'amt' => '-' . number_format(WC()->cart->coupon_discount_amounts[$code], 2, '.', ''));
             array_push($PaymentOrderItems, $Item);
             $total_discount += number_format(WC()->cart->coupon_discount_amounts[$code], 2, '.', '');
         }
     }
     if (!$this->is_wc_version_greater_2_3()) {
         if (WC()->cart->get_order_discount_total() > 0) {
             foreach (WC()->cart->get_coupons('order') as $code => $coupon) {
                 $Item = array('name' => 'Order Discount', 'number' => $code, 'qty' => '1', 'amt' => '-' . number_format(WC()->cart->coupon_discount_amounts[$code], 2, '.', ''));
                 array_push($PaymentOrderItems, $Item);
                 $total_discount += number_format(WC()->cart->coupon_discount_amounts[$code], 2, '.', '');
             }
         }
     }
     if (isset($total_discount)) {
         $total_discount = round($total_discount, 2);
     }
     if ($this->send_items) {
         /*
          * Now that all the order items are gathered, including discounts,
          * we'll push them back into the Payment.
          */
         $Payment['order_items'] = $PaymentOrderItems;
         /*
          * Now that we've looped and calculated item totals
          * we can fill in the ITEMAMT
          */
         $Payment['itemamt'] = number_format($total_items - $total_discount, 2, '.', '');
     } else {
         $Payment['order_items'] = array();
         /*
          * Now that we've looped and calculated item totals
          * we can fill in the ITEMAMT
          */
         $Payment['itemamt'] = number_format($total_items - $total_discount, 2, '.', '');
     }
     /*
      * Then we load the payment into the $Payments array
      */
     array_push($Payments, $Payment);
     $BuyerDetails = array('buyerid' => '', 'buyerusername' => '', 'buyerregistrationdate' => '');
     // For shipping options we create an array of all shipping choices similar to how order items works.
     $ShippingOptions = array();
     $Option = array('l_shippingoptionisdefault' => '', 'l_shippingoptionname' => '', 'l_shippingoptionlabel' => '', 'l_shippingoptionamount' => '');
     array_push($ShippingOptions, $Option);
     $BillingAgreements = array();
     $Item = array('l_billingtype' => '', 'l_billingagreementdescription' => '', 'l_paymenttype' => '', 'l_billingagreementcustom' => '');
     array_push($BillingAgreements, $Item);
     $PayPalRequestData = array('SECFields' => $SECFields, 'SurveyChoices' => $SurveyChoices, 'Payments' => $Payments);
     // Rounding amendment
     if (trim(number_format(WC()->cart->total, 2, '.', '')) !== trim(number_format($total_items - $total_discount + $tax + $shipping, 2, '.', ''))) {
         $diffrence_amount = $this->get_diffrent(WC()->cart->total, $total_items - $total_discount + $tax + $shipping);
         if ($shipping > 0) {
             $PayPalRequestData['Payments'][0]['shippingamt'] = round($shipping + $diffrence_amount, 2);
         } elseif ($tax > 0) {
             $PayPalRequestData['Payments'][0]['taxamt'] = round($tax + $diffrence_amount, 2);
         } else {
             $PayPalRequestData['Payments'][0]['itemamt'] = round($PayPalRequestData['Payments'][0]['itemamt'] + $diffrence_amount, 2);
         }
     }
     // Pass data into class for processing with PayPal and load the response array into $PayPalResult
     $PayPalResult = $PayPal->SetExpressCheckout($PayPalRequestData);
     /*
      * Log API result
      */
     $this->add_log('Test Mode: ' . $this->testmode);
     $this->add_log('Endpoint: ' . $this->API_Endpoint);
     $PayPalRequest = isset($PayPalResult['RAWREQUEST']) ? $PayPalResult['RAWREQUEST'] : '';
     $PayPalResponse = isset($PayPalResult['RAWRESPONSE']) ? $PayPalResult['RAWRESPONSE'] : '';
     $this->add_log('Request: ' . print_r($PayPal->NVPToArray($PayPal->MaskAPIResult($PayPalRequest)), true));
     $this->add_log('Response: ' . print_r($PayPal->NVPToArray($PayPal->MaskAPIResult($PayPalResponse)), true));
     /*
      * Error handling
      */
     if ($PayPal->APICallSuccessful($PayPalResult['ACK'])) {
         $token = urldecode($PayPalResult["TOKEN"]);
         $this->set_session('TOKEN', $token);
     }
     /*
      * Return the class library result array.
      */
     return $PayPalResult;
 }
示例#2
0
 /**
  * Get tax row amounts with or without compound taxes includes.
  *
  * @param  bool $compound True if getting compound taxes
  * @param  bool $display  True if getting total to display
  * @return float price
  */
 public function get_taxes_total($compound = true, $display = true)
 {
     $total = 0;
     foreach ($this->taxes as $key => $tax) {
         if (!$compound && WC_Tax::is_compound($key)) {
             continue;
         }
         $total += $tax;
     }
     foreach ($this->shipping_taxes as $key => $tax) {
         if (!$compound && WC_Tax::is_compound($key)) {
             continue;
         }
         $total += $tax;
     }
     if ($display) {
         $total = wc_round_tax_total($total);
     }
     return apply_filters('woocommerce_cart_taxes_total', $total, $compound, $display, $this);
 }
 /**
  * Calculate line tax - useful for gateways.
  *
  * @param mixed $item
  * @return float
  */
 public function get_line_tax($item)
 {
     return apply_filters('woocommerce_order_amount_line_tax', wc_round_tax_total($item['line_tax']), $item, $this);
 }
/**
 * @deprecated
 */
function woocommerce_round_tax_total($tax)
{
    return wc_round_tax_total($tax);
}
 /**
  * Get the refunded amount for a line item.
  *
  * @param  int $item_id ID of the item we're checking
  * @param  int $tax_id ID of the tax we're checking
  * @param  string $item_type type of the item we're checking, if not a line_item
  * @return double
  */
 public function get_tax_refunded_for_item($item_id, $tax_id, $item_type = 'line_item')
 {
     $total = 0;
     foreach ($this->get_refunds() as $refund) {
         foreach ($refund->get_items($item_type) as $refunded_item) {
             if (isset($refunded_item['refunded_item_id']) && $refunded_item['refunded_item_id'] == $item_id) {
                 switch ($item_type) {
                     case 'shipping':
                         $tax_data = maybe_unserialize($refunded_item['taxes']);
                         if (isset($tax_data[$tax_id])) {
                             $total += $tax_data[$tax_id];
                         }
                         break;
                     default:
                         $tax_data = maybe_unserialize($refunded_item['line_tax_data']);
                         if (isset($tax_data['total'][$tax_id])) {
                             $total += $tax_data['total'][$tax_id];
                         }
                         break;
                 }
             }
         }
     }
     return wc_round_tax_total($total) * -1;
 }
		</div>
	</td>

	<?php 
if (empty($legacy_order) && 'yes' == get_option('woocommerce_calc_taxes')) {
    $shipping_taxes = isset($item['taxes']) ? $item['taxes'] : '';
    $tax_data = maybe_unserialize($shipping_taxes);
    foreach ($order_taxes as $tax_item) {
        $tax_item_id = $tax_item['rate_id'];
        $tax_item_total = isset($tax_data[$tax_item_id]) ? $tax_data[$tax_item_id] : '';
        ?>

					<td class="line_tax" width="1%">
						<div class="view">
							<?php 
        echo '' != $tax_item_total ? wc_price(wc_round_tax_total($tax_item_total)) : '&ndash;';
        if ($refunded = $order->get_tax_refunded_for_item($item_id, $tax_item_id, 'shipping')) {
            echo '<small class="refunded">-' . wc_price($refunded) . '</small>';
        }
        ?>
						</div>
						<div class="edit" style="display: none;">
							<input type="text" name="shipping_taxes[<?php 
        echo absint($item_id);
        ?>
][<?php 
        echo absint($tax_item_id);
        ?>
]" placeholder="<?php 
        echo wc_format_localized_price(0);
        ?>
" class="refund_line_total wc_input_price" />
		</div>
	</td>

	<?php 
if (empty($legacy_order) && wc_tax_enabled()) {
    $shipping_taxes = isset($item['taxes']) ? $item['taxes'] : '';
    $tax_data = maybe_unserialize($shipping_taxes);
    foreach ($order_taxes as $tax_item) {
        $tax_item_id = $tax_item['rate_id'];
        $tax_item_total = isset($tax_data[$tax_item_id]) ? $tax_data[$tax_item_id] : '';
        ?>
					<td class="line_tax" width="1%">
						<div class="view">
							<?php 
        echo '' != $tax_item_total ? wc_price(wc_round_tax_total($tax_item_total), array('currency' => $order->get_order_currency())) : '&ndash;';
        if ($refunded = $order->get_tax_refunded_for_item($item_id, $tax_item_id, 'shipping')) {
            echo '<small class="refunded">-' . wc_price($refunded, array('currency' => $order->get_order_currency())) . '</small>';
        }
        ?>
						</div>
						<div class="edit" style="display: none;">
							<input type="text" name="shipping_taxes[<?php 
        echo absint($item_id);
        ?>
][<?php 
        echo esc_attr($tax_item_id);
        ?>
]" placeholder="<?php 
        echo wc_format_localized_price(0);
        ?>
 /**
  * Update recurring line taxes via AJAX
  * @see WC_Subscriptions_Order::calculate_recurring_line_taxes()
  * 
  * @since 4.4
  * @return JSON object with updated tax data
  */
 public static function ajax_update_recurring_tax()
 {
     global $wpdb;
     $woo_22_plus = version_compare(WOOCOMMERCE_VERSION, '2.2', '>=');
     check_ajax_referer('woocommerce-subscriptions', 'security');
     $order_id = absint($_POST['order_id']);
     $country = strtoupper(esc_attr($_POST['country']));
     // Step out of the way if the customer is not located in the US
     if ($country != 'US') {
         return;
     }
     $shipping = $_POST['shipping'];
     $line_subtotal = isset($_POST['line_subtotal']) ? esc_attr($_POST['line_subtotal']) : 0;
     $line_total = isset($_POST['line_total']) ? esc_attr($_POST['line_total']) : 0;
     // Set up WC_WooTax_Order object
     $order = self::get_order($order_id);
     // We only need to instantiate a WC_Tax object if we are using WooCommerce < 2.3
     if (!$woo_22_plus) {
         $tax = new WC_Tax();
     }
     $taxes = $shipping_taxes = array();
     $return = array();
     $item_data = array();
     $type_array = array();
     $product_id = '';
     if (isset($_POST['order_item_id'])) {
         $product_id = woocommerce_get_order_item_meta($_POST['order_item_id'], '_product_id');
     } elseif (isset($_POST['product_id'])) {
         $product_id = esc_attr($_POST['product_id']);
     }
     if (!empty($product_id) && WC_Subscriptions_Product::is_subscription($product_id)) {
         // Get product details
         $product = WC_Subscriptions::get_product($product_id);
         // Add product to items array
         $tic = get_post_meta($product->id, 'wootax_tic', true);
         $item_info = array('Index' => '', 'ItemID' => isset($_POST['order_item_id']) ? $_POST['order_item_id'] : $product_id, 'Qty' => 1, 'Price' => $line_subtotal > 0 ? $line_subtotal : $product->get_price(), 'Type' => 'cart');
         if (!empty($tic) && $tic) {
             $item_info['TIC'] = $tic;
         }
         $item_data[] = $item_info;
         $type_array[$_POST['order_item_id']] = 'cart';
         // Add shipping to items array
         if ($shipping > 0) {
             $item_data[] = array('Index' => '', 'ItemID' => WT_SHIPPING_ITEM, 'TIC' => WT_SHIPPING_TIC, 'Qty' => 1, 'Price' => $shipping, 'Type' => 'shipping');
             $type_array[WT_SHIPPING_ITEM] = 'shipping';
         }
         // Issue Lookup request
         $res = $order->do_lookup($item_data, $type_array, true);
         if (is_array($res)) {
             $return['recurring_shipping_tax'] = 0;
             $return['recurring_line_subtotal_tax'] = 0;
             $return['recurring_line_tax'] = 0;
             foreach ($res as $item) {
                 $item_id = $item->ItemID;
                 $item_tax = $item->TaxAmount;
                 if ($item_id == WT_SHIPPING_ITEM) {
                     $return['recurring_shipping_tax'] += $item_tax;
                 } else {
                     $return['recurring_line_subtotal_tax'] += $item_tax;
                     $return['recurring_line_tax'] += $item_tax;
                 }
             }
             $taxes[WT_RATE_ID] = $return['recurring_line_tax'];
             $shipping_taxes[WT_RATE_ID] = $return['recurring_shipping_tax'];
             // Get tax rates
             $tax_codes = array(WT_RATE_ID => apply_filters('wootax_rate_code', 'WOOTAX-RATE-DO-NOT-REMOVE'));
             // Remove old tax rows
             $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = 'recurring_tax' )", $order_id));
             $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = 'recurring_tax'", $order_id));
             // Now merge to keep tax rows
             ob_start();
             foreach (array_keys($taxes + $shipping_taxes) as $key) {
                 $item = array();
                 $item['rate_id'] = $key;
                 $item['name'] = $tax_codes[$key];
                 $item['label'] = $woo_22_plus ? WC_Tax::get_rate_label($key) : $tax->get_rate_label($key);
                 $item['compound'] = $woo_22_plus ? WC_Tax::is_compound($key) : $tax->is_compound($key) ? 1 : 0;
                 $item['tax_amount'] = wc_round_tax_total(isset($taxes[$key]) ? $taxes[$key] : 0);
                 $item['shipping_tax_amount'] = wc_round_tax_total(isset($shipping_taxes[$key]) ? $shipping_taxes[$key] : 0);
                 if (!$item['label']) {
                     $item['label'] = WC()->countries->tax_or_vat();
                 }
                 // Add line item
                 $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $item['name'], 'order_item_type' => 'recurring_tax'));
                 // Add line item meta
                 if ($item_id) {
                     woocommerce_add_order_item_meta($item_id, 'rate_id', $item['rate_id']);
                     woocommerce_add_order_item_meta($item_id, 'label', $item['label']);
                     woocommerce_add_order_item_meta($item_id, 'compound', $item['compound']);
                     woocommerce_add_order_item_meta($item_id, 'tax_amount', $item['tax_amount']);
                     woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', $item['shipping_tax_amount']);
                 }
                 include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-tax-html.php';
             }
             $return['tax_row_html'] = ob_get_clean();
             echo json_encode($return);
         }
     }
     die;
 }
 /**
  * Get the order data for a single CSV row
  *
  * Note items are keyed according to the column header keys above so these can be modified using
  * the provider filter without needing to worry about the array order
  *
  * @since 3.0
  * @param int $order_id the WC_Order ID
  * @return array order data in the format key => content
  */
 private function get_orders_csv_row($order_id)
 {
     $order = wc_get_order($order_id);
     $line_items = $shipping_items = $fee_items = $tax_items = $coupon_items = array();
     // get line items
     foreach ($order->get_items() as $item_id => $item) {
         $product = $order->get_product_from_item($item);
         if (!is_object($product)) {
             $product = new WC_Product(0);
         }
         $item_meta = new WC_Order_Item_Meta(SV_WC_Plugin_Compatibility::is_wc_version_gte_2_4() ? $item : $item['item_meta']);
         $meta = $item_meta->display(true, true);
         if ($meta) {
             // remove newlines
             $meta = str_replace(array("\r", "\r\n", "\n"), '', $meta);
             // switch reserved chars (:;|) to =
             $meta = str_replace(array(': ', ':', ';', '|'), '=', $meta);
         }
         $line_item = array('name' => html_entity_decode($product->get_title() ? $product->get_title() : $item['name'], ENT_NOQUOTES, 'UTF-8'), 'sku' => $product->get_sku(), 'quantity' => $item['qty'], 'total' => wc_format_decimal($order->get_line_total($item), 2), 'refunded' => wc_format_decimal($order->get_total_refunded_for_item($item_id), 2), 'meta' => html_entity_decode($meta, ENT_NOQUOTES, 'UTF-8'));
         // add line item tax
         $line_tax_data = isset($item['line_tax_data']) ? $item['line_tax_data'] : array();
         $tax_data = maybe_unserialize($line_tax_data);
         $line_item['tax'] = isset($tax_data['total']) ? wc_format_decimal(wc_round_tax_total(array_sum((array) $tax_data['total'])), 2) : '';
         /**
          * CSV Order Export Line Item.
          *
          * Filter the individual line item entry for the default export
          *
          * @since 3.0.6
          * @param array $line_item {
          *     line item data in key => value format
          *     the keys are for convenience and not used for exporting. Make
          *     sure to prefix the values with the desired line item entry name
          * }
          *
          * @param array $item WC order item data
          * @param WC_Product $product the product
          * @param WC_Order $order the order
          * @param \WC_Customer_Order_CSV_Export_Generator $this, generator instance
          */
         $line_item = apply_filters('wc_customer_order_csv_export_order_line_item', $line_item, $item, $product, $order, $this);
         if ('default_one_row_per_item' !== $this->order_format && is_array($line_item)) {
             foreach ($line_item as $name => $value) {
                 $line_item[$name] = $name . ':' . $value;
             }
             $line_item = implode('|', $line_item);
         }
         if ($line_item) {
             $line_items[] = $line_item;
         }
     }
     foreach ($order->get_shipping_methods() as $_ => $shipping_item) {
         $shipping_items[] = implode('|', array('method:' . $shipping_item['name'], 'total:' . wc_format_decimal($shipping_item['cost'], 2)));
     }
     // get fee items & total
     $fee_total = 0;
     $fee_tax_total = 0;
     foreach ($order->get_fees() as $fee_id => $fee) {
         $fee_items[] = implode('|', array('name:' . $fee['name'], 'total:' . wc_format_decimal($fee['line_total'], 2), 'tax:' . wc_format_decimal($fee['line_tax'], 2)));
         $fee_total += $fee['line_total'];
         $fee_tax_total += $fee['line_tax'];
     }
     // get tax items
     foreach ($order->get_tax_totals() as $tax_code => $tax) {
         $tax_items[] = implode('|', array('code:' . $tax_code, 'total:' . wc_format_decimal($tax->amount, 2)));
     }
     // add coupons
     foreach ($order->get_items('coupon') as $_ => $coupon_item) {
         $coupon = new WC_Coupon($coupon_item['name']);
         $coupon_post = get_post($coupon->id);
         $coupon_items[] = implode('|', array('code:' . $coupon_item['name'], 'description:' . (is_object($coupon_post) ? $coupon_post->post_excerpt : ''), 'amount:' . wc_format_decimal($coupon_item['discount_amount'], 2)));
     }
     $order_data = array('order_id' => $order->id, 'order_number' => $order->get_order_number(), 'order_date' => $order->order_date, 'status' => $order->get_status(), 'shipping_total' => $order->get_total_shipping(), 'shipping_tax_total' => wc_format_decimal($order->get_shipping_tax(), 2), 'fee_total' => wc_format_decimal($fee_total, 2), 'fee_tax_total' => wc_format_decimal($fee_tax_total, 2), 'tax_total' => wc_format_decimal($order->get_total_tax(), 2), 'cart_discount' => SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3() ? wc_format_decimal($order->get_total_discount(), 2) : wc_format_decimal($order->get_cart_discount(), 2), 'order_discount' => SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3() ? wc_format_decimal($order->get_total_discount(), 2) : wc_format_decimal($order->get_order_discount(), 2), 'discount_total' => wc_format_decimal($order->get_total_discount(), 2), 'order_total' => wc_format_decimal($order->get_total(), 2), 'refunded_total' => wc_format_decimal($order->get_total_refunded(), 2), 'order_currency' => $order->get_order_currency(), 'payment_method' => $order->payment_method, 'shipping_method' => $order->get_shipping_method(), 'customer_id' => $order->get_user_id(), 'billing_first_name' => $order->billing_first_name, 'billing_last_name' => $order->billing_last_name, 'billing_company' => $order->billing_company, 'billing_email' => $order->billing_email, 'billing_phone' => $order->billing_phone, 'billing_address_1' => $order->billing_address_1, 'billing_address_2' => $order->billing_address_2, 'billing_postcode' => $order->billing_postcode, 'billing_city' => $order->billing_city, 'billing_state' => $order->billing_state, 'billing_country' => $order->billing_country, 'shipping_first_name' => $order->shipping_first_name, 'shipping_last_name' => $order->shipping_last_name, 'shipping_company' => $order->shipping_company, 'shipping_address_1' => $order->shipping_address_1, 'shipping_address_2' => $order->shipping_address_2, 'shipping_postcode' => $order->shipping_postcode, 'shipping_city' => $order->shipping_city, 'shipping_state' => $order->shipping_state, 'shipping_country' => $order->shipping_country, 'customer_note' => $order->customer_note, 'shipping_items' => implode(';', $shipping_items), 'fee_items' => implode(';', $fee_items), 'tax_items' => implode(';', $tax_items), 'coupon_items' => implode(';', $coupon_items), 'order_notes' => implode('|', $this->get_order_notes($order)), 'download_permissions' => $order->download_permissions_granted ? $order->download_permissions_granted : 0);
     if ('default_one_row_per_item' === $this->order_format) {
         $new_order_data = array();
         foreach ($line_items as $item) {
             $order_data['item_name'] = $item['name'];
             $order_data['item_sku'] = $item['sku'];
             $order_data['item_quantity'] = $item['quantity'];
             $order_data['item_tax'] = $item['tax'];
             $order_data['item_total'] = $item['total'];
             $order_data['item_refunded'] = $item['refunded'];
             $order_data['item_meta'] = $item['meta'];
             /**
              * CSV Order Export Row for One Row per Item.
              *
              * Filter the individual row data for the order export
              *
              * @since 3.3.0
              * @param array $order_data {
              *     order data in key => value format
              *     to modify the row data, ensure the key matches any of the header keys and set your own value
              * }
              * @param array $item
              * @param \WC_Order $order WC Order object
              * @param \WC_Customer_Order_CSV_Export_Generator $this, generator instance
              */
             $new_order_data[] = apply_filters('wc_customer_order_csv_export_order_row_one_row_per_item', $order_data, $item, $order, $this);
         }
         $order_data = $new_order_data;
     } else {
         $order_data['line_items'] = implode(';', $line_items);
     }
     /**
      * CSV Order Export Row.
      *
      * Filter the individual row data for the order export
      *
      * @since 3.0
      * @param array $order_data {
      *     order data in key => value format
      *     to modify the row data, ensure the key matches any of the header keys and set your own value
      * }
      * @param \WC_Order $order WC Order object
      * @param \WC_Customer_Order_CSV_Export_Generator $this, generator instance
      */
     return apply_filters('wc_customer_order_csv_export_order_row', $order_data, $order, $this);
 }
示例#10
0
" class="line_total wc_input_price" /></label>
		</div>
	</td>

	<?php 
if (get_option('woocommerce_calc_taxes') == 'yes') {
    ?>

	<td class="line_tax" width="1%">
		<div class="view">
			<?php 
    if (isset($item['line_tax'])) {
        if (isset($item['line_subtotal_tax']) && $item['line_subtotal_tax'] != $item['line_tax']) {
            echo '<del>' . wc_price(wc_round_tax_total($item['line_subtotal_tax'])) . '</del> ';
        }
        echo wc_price(wc_round_tax_total($item['line_tax']));
    }
    ?>
		</div>
		<div class="edit" style="display:none">
			<span class="subtotal"><input type="text" name="line_subtotal_tax[<?php 
    echo absint($item_id);
    ?>
]" placeholder="<?php 
    echo wc_format_localized_price(0);
    ?>
" value="<?php 
    if (isset($item['line_subtotal_tax'])) {
        echo esc_attr(wc_format_localized_price($item['line_subtotal_tax']));
    }
    ?>
    /**
     * Get the main chart
     *
     * @return string
     */
    public function get_main_chart()
    {
        global $wpdb;
        $tax_rows = $this->get_order_report_data(array('data' => array('order_item_name' => array('type' => 'order_item', 'function' => '', 'name' => 'tax_rate'), 'tax_amount' => array('type' => 'order_item_meta', 'order_item_type' => 'tax', 'function' => '', 'name' => 'tax_amount'), 'shipping_tax_amount' => array('type' => 'order_item_meta', 'order_item_type' => 'tax', 'function' => '', 'name' => 'shipping_tax_amount'), 'rate_id' => array('type' => 'order_item_meta', 'order_item_type' => 'tax', 'function' => '', 'name' => 'rate_id'), 'order_id' => array('type' => 'order_item', 'function' => '', 'name' => 'order_id')), 'where' => array(array('key' => 'order_item_type', 'value' => 'tax', 'operator' => '='), array('key' => 'order_item_name', 'value' => '', 'operator' => '!=')), 'order_by' => 'post_date ASC', 'query_type' => 'get_results', 'filter_range' => true));
        ?>
		<table class="widefat">
			<thead>
				<tr>
					<th><?php 
        _e('Tax', 'woocommerce');
        ?>
</th>
					<th><?php 
        _e('Rate', 'woocommerce');
        ?>
</th>
					<th class="total_row"><?php 
        _e('Number of orders', 'woocommerce');
        ?>
</th>
					<th class="total_row"><?php 
        _e('Tax Amount', 'woocommerce');
        ?>
 <a class="tips" data-tip="<?php 
        esc_attr_e('This is the sum of the "Tax Rows" tax amount within your orders.', 'woocommerce');
        ?>
" href="#">[?]</a></th>
					<th class="total_row"><?php 
        _e('Shipping Tax Amount', 'woocommerce');
        ?>
 <a class="tips" data-tip="<?php 
        esc_attr_e('This is the sum of the "Tax Rows" shipping tax amount within your orders.', 'woocommerce');
        ?>
" href="#">[?]</a></th>
					<th class="total_row"><?php 
        _e('Total Tax', 'woocommerce');
        ?>
 <a class="tips" data-tip="<?php 
        esc_attr_e('This is the total tax for the rate (shipping tax + product tax).', 'woocommerce');
        ?>
" href="#">[?]</a></th>
				</tr>
			</thead>
			<?php 
        if ($tax_rows) {
            ?>
				<tbody>
					<?php 
            $grouped_tax_tows = array();
            foreach ($tax_rows as $tax_row) {
                if (!isset($grouped_tax_tows[$tax_row->rate_id])) {
                    $grouped_tax_tows[$tax_row->rate_id] = (object) array('tax_rate' => $tax_row->tax_rate, 'total_orders' => 0, 'tax_amount' => 0, 'shipping_tax_amount' => 0);
                }
                if ('shop_order' === get_post_type($tax_row->order_id)) {
                    $grouped_tax_tows[$tax_row->rate_id]->total_orders++;
                }
                $grouped_tax_tows[$tax_row->rate_id]->tax_amount += wc_round_tax_total($tax_row->tax_amount);
                $grouped_tax_tows[$tax_row->rate_id]->shipping_tax_amount += wc_round_tax_total($tax_row->shipping_tax_amount);
            }
            foreach ($grouped_tax_tows as $rate_id => $tax_row) {
                $rate = $wpdb->get_var($wpdb->prepare("SELECT tax_rate FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id));
                ?>
						<tr>
							<th scope="row"><?php 
                echo $tax_row->tax_rate;
                ?>
</th>
							<td><?php 
                echo $rate;
                ?>
%</td>
							<td class="total_row"><?php 
                echo $tax_row->total_orders;
                ?>
</td>
							<td class="total_row"><?php 
                echo wc_price($tax_row->tax_amount);
                ?>
</td>
							<td class="total_row"><?php 
                echo wc_price($tax_row->shipping_tax_amount);
                ?>
</td>
							<td class="total_row"><?php 
                echo wc_price($tax_row->tax_amount + $tax_row->shipping_tax_amount);
                ?>
</td>
						</tr>
						<?php 
            }
            ?>
				</tbody>
				<tfoot>
					<tr>
						<th scope="row" colspan="3"><?php 
            _e('Total', 'woocommerce');
            ?>
</th>
						<th class="total_row"><?php 
            echo wc_price(wc_round_tax_total(array_sum(wp_list_pluck((array) $tax_rows, 'tax_amount'))));
            ?>
</th>
						<th class="total_row"><?php 
            echo wc_price(wc_round_tax_total(array_sum(wp_list_pluck((array) $tax_rows, 'shipping_tax_amount'))));
            ?>
</th>
						<th class="total_row"><strong><?php 
            echo wc_price(wc_round_tax_total(array_sum(wp_list_pluck((array) $tax_rows, 'tax_amount')) + array_sum(wp_list_pluck((array) $tax_rows, 'shipping_tax_amount'))));
            ?>
</strong></th>
					</tr>
				</tfoot>
			<?php 
        } else {
            ?>
				<tbody>
					<tr>
						<td><?php 
            _e('No taxes found in this period', 'woocommerce');
            ?>
</td>
					</tr>
				</tbody>
			<?php 
        }
        ?>
		</table>
		<?php 
    }
 /**
  * Store an order as a transaction in Taxamo
  *
  * @param WC_Order $order
  * @param bool $force_country
  */
 public function store_transaction($order, $force_country)
 {
     // Get the billing country
     $billing_country = $order->billing_country;
     // The order manager
     $order_manager = new WC_TA_Order_Manager();
     // The transaction extra
     $transaction_extra = array();
     // Location confirmation
     if (true === $force_country) {
         // Set force country code
         $transaction_extra['force_country_code'] = $billing_country;
     }
     // Check for VAT number
     $vat_number = get_post_meta($order->id, WC_TA_Vat_Number_Field::META_KEY, true);
     if ('' !== $vat_number) {
         // Set VAT number
         $transaction_extra['buyer_tax_number'] = $vat_number;
     }
     // Check for shipping/handling cost
     if ($order->order_shipping > 0) {
         // Transaction lines
         $transaction_extra['transaction_lines'] = array();
         // Get the shipping line items
         $shipping_line_items = $order->get_items('shipping');
         // Check if there are line items
         if (count($shipping_line_items) > 0) {
             // Loop
             foreach ($shipping_line_items as $shipping_line_item_key => $shipping_line_item) {
                 // Calculate some taxes
                 $line_cost = $shipping_line_item['cost'];
                 // Array of taxes
                 $line_taxes = maybe_unserialize($shipping_line_item['taxes']);
                 // Get total tax
                 $line_tax_total = 0;
                 if (is_array($line_taxes)) {
                     $line_tax_total = array_sum($line_taxes);
                 }
                 // Calculate shipping tax of this line item
                 $shipping_tax_rate = 0;
                 if ($order->order_shipping_tax > 0) {
                     $shipping_tax_rate = $line_tax_total / $line_cost * 100;
                 }
                 // Add shipping line item to transaction line
                 $transaction_extra['transaction_lines'][] = array('product_type' => 'default', 'custom_id' => "" . $shipping_line_item_key, 'quantity' => 1, 'tax_rate' => $shipping_tax_rate, 'total_amount' => wc_round_tax_total($line_cost + $line_tax_total), 'description' => $shipping_line_item['name'], 'informative' => true);
             }
         }
     }
     // Setup request
     $request_store_transaction = new WC_TA_Request_Store_Transaction($billing_country, $order_manager->get_items_from_order($order), $order->billing_first_name . ' ' . $order->billing_last_name, $order->billing_email, $order->id, $transaction_extra);
     // Do request
     if ($request_store_transaction->do_request()) {
         // Get the body
         $response_body = $request_store_transaction->get_response_body();
         if (isset($response_body->transaction)) {
             // Attach transaction to order
             update_post_meta($order->id, 'taxamo_transaction_key', $response_body->transaction->key);
             // Loop through line items
             if (count($response_body->transaction->transaction_lines) > 0) {
                 foreach ($response_body->transaction->transaction_lines as $transaction_line) {
                     if (isset($transaction_line->custom_id) && isset($transaction_line->line_key)) {
                         // Add Taxamo line key to order item
                         wc_add_order_item_meta($transaction_line->custom_id, self::OIM_LINE_KEY, $transaction_line->line_key, true);
                     }
                 }
             }
         }
     } else {
         /**
          * @todo Better error handling. Check if AJAX is updated correctly is country doesn't match first try but does second try.
          * Block order button
          */
         if (function_exists('wc_add_notice')) {
             wc_add_notice($request_store_transaction->get_error_message(), 'error');
         }
     }
 }
 /**
  * Get the order data for a single CSV row
  *
  * Note items are keyed according to the column header keys above so these can be modified using
  * the provider filter without needing to worry about the array order
  *
  * @since 3.0
  * @param int $order_id the WC_Order ID
  * @return array order data in the format key => content
  */
 private function get_orders_csv_row($order_id)
 {
     $order = wc_get_order($order_id);
     $is_json = 'import' == $this->order_format;
     $line_items = $shipping_items = $fee_items = $tax_items = $coupon_items = array();
     // get line items
     foreach ($order->get_items() as $item_id => $item) {
         $product = $order->get_product_from_item($item);
         if (!is_object($product)) {
             $product = new WC_Product(0);
         }
         $item_meta = new WC_Order_Item_Meta($item);
         if ($is_json) {
             $meta = array();
             foreach ($item_meta->get_formatted('_') as $meta_key => $formatted_meta) {
                 $meta[$formatted_meta['key']] = $formatted_meta['value'];
             }
         } else {
             add_filter('woocommerce_attribute_label', array($this, 'escape_reserved_meta_chars'));
             add_filter('woocommerce_order_item_display_meta_value', array($this, 'escape_reserved_meta_chars'));
             $meta = $item_meta->display(true, true);
             remove_filter('woocommerce_attribute_label', array($this, 'escape_reserved_meta_chars'));
             remove_filter('woocommerce_order_item_display_meta_value', array($this, 'escape_reserved_meta_chars'));
             if ($meta) {
                 // replace key-value sperator (': ') with our own - equals sign (=)
                 $meta = str_replace(': ', '=', $meta);
                 // remove any newlines generated by WC_Order_Item_Meta::display()
                 $meta = str_replace(array(", \r\n", ", \r", ", \n"), ',', $meta);
                 // re-insert colons and newlines
                 $meta = str_replace(array('[INSERT_COLON_HERE]', '[INSERT_NEWLINE_HERE]'), array(':', "\n"), $meta);
             }
         }
         $product = $order->get_product_from_item($item);
         $product_id = null;
         $product_sku = null;
         // Check if the product exists.
         if (is_object($product)) {
             $product_id = isset($product->variation_id) ? $product->variation_id : $product->id;
             $product_sku = $product->get_sku();
         }
         if ($is_json) {
             $line_item = array('id' => $item_id, 'subtotal' => wc_format_decimal($order->get_line_subtotal($item), 2), 'subtotal_tax' => wc_format_decimal($item['line_subtotal_tax'], 2), 'total' => wc_format_decimal($order->get_line_total($item), 2), 'total_tax' => wc_format_decimal($order->get_line_tax($item), 2), 'quantity' => (int) $item['qty'], 'name' => $item['name'], 'product_id' => $product_id, 'sku' => $product_sku, 'meta' => $meta, 'tax_data' => isset($item['line_tax_data']) ? maybe_unserialize($item['line_tax_data']) : '');
         } else {
             $line_item = array('name' => html_entity_decode($item['name'], ENT_NOQUOTES, 'UTF-8'), 'sku' => $product_sku, 'quantity' => (int) $item['qty'], 'total' => wc_format_decimal($order->get_line_total($item), 2), 'refunded' => wc_format_decimal($order->get_total_refunded_for_item($item_id), 2), 'refunded_qty' => $order->get_qty_refunded_for_item($item_id), 'meta' => is_string($meta) ? html_entity_decode($meta, ENT_NOQUOTES, 'UTF-8') : $meta);
             // add line item tax
             $line_tax_data = isset($item['line_tax_data']) ? $item['line_tax_data'] : array();
             $tax_data = maybe_unserialize($line_tax_data);
             $line_item['tax'] = isset($tax_data['total']) ? wc_format_decimal(wc_round_tax_total(array_sum((array) $tax_data['total'])), 2) : '';
         }
         /**
          * CSV Order Export Line Item.
          *
          * Filter the individual line item entry for the default export
          *
          * @since 3.0.6
          * @param array $line_item {
          *     line item data in key => value format
          *     the keys are for convenience and not used for exporting. Make
          *     sure to prefix the values with the desired line item entry name
          * }
          *
          * @param array $item WC order item data
          * @param WC_Product $product the product
          * @param WC_Order $order the order
          * @param \WC_Customer_Order_CSV_Export_Generator $this, generator instance
          */
         $line_item = apply_filters('wc_customer_order_csv_export_order_line_item', $line_item, $item, $product, $order, $this);
         if (!in_array($this->order_format, array('default_one_row_per_item', 'import')) && is_array($line_item)) {
             foreach ($line_item as $name => $value) {
                 $name = $this->escape_reserved_item_chars($name);
                 $value = $this->escape_reserved_item_chars($value);
                 $line_item[$name] = $name . ':' . $value;
             }
             $line_item = implode('|', $line_item);
         }
         if ($line_item) {
             $line_items[] = $line_item;
         }
     }
     foreach ($order->get_shipping_methods() as $shipping_item_id => $shipping_item) {
         $shipping_item = array('id' => $shipping_item_id, 'method_id' => $shipping_item['method_id'], 'method_title' => $shipping_item['name'], 'total' => wc_format_decimal($shipping_item['cost'], 2), 'taxes' => isset($shipping_item['taxes']) ? maybe_unserialize($shipping_item['taxes']) : '');
         if ($is_json) {
             $shipping_items[] = $shipping_item;
         } else {
             $shipping_items[] = implode('|', array('method:' . $this->escape_reserved_item_chars($shipping_item['method_title']), 'total:' . $shipping_item['total']));
         }
     }
     // get fee items & total
     $fee_total = 0;
     $fee_tax_total = 0;
     foreach ($order->get_fees() as $fee_item_id => $fee_item) {
         $fee = array('id' => $fee_item_id, 'title' => $fee_item['name'], 'tax_class' => !empty($fee_item['tax_class']) ? $fee_item['tax_class'] : null, 'total' => wc_format_decimal($order->get_line_total($fee_item), 2), 'total_tax' => wc_format_decimal($order->get_line_tax($fee_item), 2), 'tax_data' => isset($fee_item['line_tax_data']) ? maybe_unserialize($fee_item['line_tax_data']) : '');
         if ($is_json) {
             if (null !== $fee['tax_class']) {
                 $fee['taxable'] = true;
             }
             $fee_items[] = $fee;
         } else {
             $fee_items[] = implode('|', array('name:' . $this->escape_reserved_item_chars($fee['title']), 'total:' . $fee['total'], 'tax:' . $fee['total_tax']));
         }
         $fee_total += $fee_item['line_total'];
         $fee_tax_total += $fee_item['line_tax'];
     }
     // get tax items
     foreach ($order->get_tax_totals() as $tax_code => $tax) {
         $tax_item = array('id' => $tax->id, 'rate_id' => $tax->rate_id, 'code' => $tax_code, 'title' => $tax->label, 'total' => wc_format_decimal($tax->amount, 2), 'compound' => (bool) $tax->is_compound);
         if ($is_json) {
             $tax_items[] = $tax_item;
         } else {
             $tax_items[] = implode('|', array('code:' . $this->escape_reserved_item_chars($tax_code), 'total:' . $tax->amount));
         }
     }
     // add coupons
     foreach ($order->get_items('coupon') as $coupon_item_id => $coupon_item) {
         $coupon_item = array('id' => $coupon_item_id, 'code' => $coupon_item['name'], 'amount' => wc_format_decimal($coupon_item['discount_amount'], 2));
         if ($is_json) {
             $coupon_items[] = $coupon_item;
         } else {
             $coupon = new WC_Coupon($coupon_item['code']);
             $coupon_post = get_post($coupon->id);
             $coupon_items[] = implode('|', array('code:' . $this->escape_reserved_item_chars($coupon_item['code']), 'description:' . $this->escape_reserved_item_chars(is_object($coupon_post) ? $coupon_post->post_excerpt : ''), 'amount:' . $coupon_item['amount']));
         }
     }
     $order_data = array('order_id' => $order->id, 'order_number' => $order->get_order_number(), 'order_date' => $order->order_date, 'status' => $order->get_status(), 'shipping_total' => $order->get_total_shipping(), 'shipping_tax_total' => wc_format_decimal($order->get_shipping_tax(), 2), 'fee_total' => wc_format_decimal($fee_total, 2), 'fee_tax_total' => wc_format_decimal($fee_tax_total, 2), 'tax_total' => wc_format_decimal($order->get_total_tax(), 2), 'discount_total' => wc_format_decimal($order->get_total_discount(), 2), 'order_total' => wc_format_decimal($order->get_total(), 2), 'refunded_total' => wc_format_decimal($order->get_total_refunded(), 2), 'order_currency' => $order->get_order_currency(), 'payment_method' => $order->payment_method, 'shipping_method' => $order->get_shipping_method(), 'customer_id' => $order->get_user_id(), 'billing_first_name' => $order->billing_first_name, 'billing_last_name' => $order->billing_last_name, 'billing_company' => $order->billing_company, 'billing_email' => $order->billing_email, 'billing_phone' => $order->billing_phone, 'billing_address_1' => $order->billing_address_1, 'billing_address_2' => $order->billing_address_2, 'billing_postcode' => $order->billing_postcode, 'billing_city' => $order->billing_city, 'billing_state' => $order->billing_state, 'billing_country' => $order->billing_country, 'shipping_first_name' => $order->shipping_first_name, 'shipping_last_name' => $order->shipping_last_name, 'shipping_company' => $order->shipping_company, 'shipping_address_1' => $order->shipping_address_1, 'shipping_address_2' => $order->shipping_address_2, 'shipping_postcode' => $order->shipping_postcode, 'shipping_city' => $order->shipping_city, 'shipping_state' => $order->shipping_state, 'shipping_country' => $order->shipping_country, 'customer_note' => $order->customer_note, 'shipping_items' => $is_json && !empty($shipping_items) ? json_encode($shipping_items) : implode(';', $shipping_items), 'fee_items' => $is_json && !empty($fee_items) ? json_encode($fee_items) : implode(';', $fee_items), 'tax_items' => $is_json && !empty($tax_items) ? json_encode($tax_items) : implode(';', $tax_items), 'coupon_items' => $is_json && !empty($coupon_items) ? json_encode($coupon_items) : implode(';', $coupon_items), 'order_notes' => implode('|', $this->get_order_notes($order)), 'download_permissions' => $order->download_permissions_granted ? $order->download_permissions_granted : 0);
     if ('default_one_row_per_item' === $this->order_format) {
         $new_order_data = array();
         foreach ($line_items as $item) {
             $order_data['item_name'] = $item['name'];
             $order_data['item_sku'] = $item['sku'];
             $order_data['item_quantity'] = $item['quantity'];
             $order_data['item_tax'] = $item['tax'];
             $order_data['item_total'] = $item['total'];
             $order_data['item_refunded'] = $item['refunded'];
             $order_data['item_refunded_qty'] = $item['refunded_qty'];
             $order_data['item_meta'] = $item['meta'];
             /**
              * CSV Order Export Row for One Row per Item.
              *
              * Filter the individual row data for the order export
              *
              * @since 3.3.0
              * @param array $order_data {
              *     order data in key => value format
              *     to modify the row data, ensure the key matches any of the header keys and set your own value
              * }
              * @param array $item
              * @param \WC_Order $order WC Order object
              * @param \WC_Customer_Order_CSV_Export_Generator $this, generator instance
              */
             $new_order_data[] = apply_filters('wc_customer_order_csv_export_order_row_one_row_per_item', $order_data, $item, $order, $this);
         }
         $order_data = $new_order_data;
     } else {
         $order_data['line_items'] = $is_json ? json_encode($line_items) : implode(';', $line_items);
     }
     /**
      * CSV Order Export Row.
      *
      * Filter the individual row data for the order export
      *
      * @since 3.0
      * @param array $order_data {
      *     order data in key => value format
      *     to modify the row data, ensure the key matches any of the header keys and set your own value
      * }
      * @param \WC_Order $order WC Order object
      * @param \WC_Customer_Order_CSV_Export_Generator $this, generator instance
      */
     return apply_filters('wc_customer_order_csv_export_order_row', $order_data, $order, $this);
 }
示例#14
0
 /**
  * create_order function.
  * @access public
  * @throws Exception
  * @return int
  */
 public function create_order()
 {
     global $wpdb;
     // Give plugins the opportunity to create an order themselves
     $order_id = apply_filters('woocommerce_create_order', null, $this);
     if (is_numeric($order_id)) {
         return $order_id;
     }
     // Create Order (send cart variable so we can record items and reduce inventory). Only create if this is a new order, not if the payment was rejected.
     $order_data = apply_filters('woocommerce_new_order_data', array('post_type' => 'shop_order', 'post_title' => sprintf(__('Order &ndash; %s', 'woocommerce'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce'))), 'post_status' => 'publish', 'ping_status' => 'closed', 'post_excerpt' => isset($this->posted['order_comments']) ? $this->posted['order_comments'] : '', 'post_author' => 1, 'post_password' => uniqid('order_')));
     // Insert or update the post data
     $create_new_order = true;
     if (WC()->session->order_awaiting_payment > 0) {
         $order_id = absint(WC()->session->order_awaiting_payment);
         /* Check order is unpaid by getting its status */
         $terms = wp_get_object_terms($order_id, 'shop_order_status', array('fields' => 'slugs'));
         $order_status = isset($terms[0]) ? $terms[0] : 'pending';
         // Resume the unpaid order if its pending
         if ($order_status == 'pending' || $order_status == 'failed') {
             // Update the existing order as we are resuming it
             $create_new_order = false;
             $order_data['ID'] = $order_id;
             wp_update_post($order_data);
             // Clear the old line items - we'll add these again in case they changed
             $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $order_id));
             $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $order_id));
             // Trigger an action for the resumed order
             do_action('woocommerce_resume_order', $order_id);
         }
     }
     if ($create_new_order) {
         $order_id = wp_insert_post($order_data, true);
         if (is_wp_error($order_id)) {
             throw new Exception('Error: Unable to create order. Please try again.');
         } else {
             do_action('woocommerce_new_order', $order_id);
         }
     }
     // Store user data
     if ($this->checkout_fields['billing']) {
         foreach ($this->checkout_fields['billing'] as $key => $field) {
             update_post_meta($order_id, '_' . $key, $this->posted[$key]);
             if ($this->customer_id && apply_filters('woocommerce_checkout_update_customer_data', true, $this)) {
                 update_user_meta($this->customer_id, $key, $this->posted[$key]);
             }
         }
     }
     if ($this->checkout_fields['shipping'] && WC()->cart->needs_shipping()) {
         foreach ($this->checkout_fields['shipping'] as $key => $field) {
             $postvalue = false;
             if ($this->posted['ship_to_different_address'] == false) {
                 if (isset($this->posted[str_replace('shipping_', 'billing_', $key)])) {
                     $postvalue = $this->posted[str_replace('shipping_', 'billing_', $key)];
                     update_post_meta($order_id, '_' . $key, $postvalue);
                 }
             } else {
                 $postvalue = $this->posted[$key];
                 update_post_meta($order_id, '_' . $key, $postvalue);
             }
             // User
             if ($postvalue && $this->customer_id && apply_filters('woocommerce_checkout_update_customer_data', true, $this)) {
                 update_user_meta($this->customer_id, $key, $postvalue);
             }
         }
     }
     // Save any other user meta
     if ($this->customer_id) {
         do_action('woocommerce_checkout_update_user_meta', $this->customer_id, $this->posted);
     }
     // Store the line items to the new/resumed order
     foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
         $_product = $values['data'];
         // Add line item
         $item_id = wc_add_order_item($order_id, array('order_item_name' => $_product->get_title(), 'order_item_type' => 'line_item'));
         // Add line item meta
         if ($item_id) {
             wc_add_order_item_meta($item_id, '_qty', apply_filters('woocommerce_stock_amount', $values['quantity']));
             wc_add_order_item_meta($item_id, '_tax_class', $_product->get_tax_class());
             wc_add_order_item_meta($item_id, '_product_id', $values['product_id']);
             wc_add_order_item_meta($item_id, '_variation_id', $values['variation_id']);
             wc_add_order_item_meta($item_id, '_line_subtotal', wc_format_decimal($values['line_subtotal']));
             wc_add_order_item_meta($item_id, '_line_total', wc_format_decimal($values['line_total']));
             wc_add_order_item_meta($item_id, '_line_tax', wc_format_decimal($values['line_tax']));
             wc_add_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($values['line_subtotal_tax']));
             // Store variation data in meta so admin can view it
             if ($values['variation'] && is_array($values['variation'])) {
                 foreach ($values['variation'] as $key => $value) {
                     wc_add_order_item_meta($item_id, esc_attr(str_replace('attribute_', '', $key)), $value);
                 }
             }
             // Add line item meta for backorder status
             if ($_product->backorders_require_notification() && $_product->is_on_backorder($values['quantity'])) {
                 wc_add_order_item_meta($item_id, apply_filters('woocommerce_backordered_item_meta_name', __('Backordered', 'woocommerce'), $cart_item_key, $order_id), $values['quantity'] - max(0, $_product->get_total_stock()));
             }
             // Allow plugins to add order item meta
             do_action('woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key);
         }
     }
     // Store fees
     foreach (WC()->cart->get_fees() as $fee) {
         $item_id = wc_add_order_item($order_id, array('order_item_name' => $fee->name, 'order_item_type' => 'fee'));
         if ($fee->taxable) {
             wc_add_order_item_meta($item_id, '_tax_class', $fee->tax_class);
         } else {
             wc_add_order_item_meta($item_id, '_tax_class', '0');
         }
         wc_add_order_item_meta($item_id, '_line_total', wc_format_decimal($fee->amount));
         wc_add_order_item_meta($item_id, '_line_tax', wc_format_decimal($fee->tax));
     }
     // Store shipping for all packages
     $packages = WC()->shipping->get_packages();
     foreach ($packages as $i => $package) {
         if (isset($package['rates'][$this->shipping_methods[$i]])) {
             $method = $package['rates'][$this->shipping_methods[$i]];
             $item_id = wc_add_order_item($order_id, array('order_item_name' => $method->label, 'order_item_type' => 'shipping'));
             if ($item_id) {
                 wc_add_order_item_meta($item_id, 'method_id', $method->id);
                 wc_add_order_item_meta($item_id, 'cost', wc_format_decimal($method->cost));
                 do_action('woocommerce_add_shipping_order_item', $order_id, $item_id, $i);
             }
         }
     }
     // Store tax rows
     foreach (array_keys(WC()->cart->taxes + WC()->cart->shipping_taxes) as $key) {
         $item_id = wc_add_order_item($order_id, array('order_item_name' => WC()->cart->tax->get_rate_code($key), 'order_item_type' => 'tax'));
         // Add line item meta
         if ($item_id) {
             wc_add_order_item_meta($item_id, 'rate_id', $key);
             wc_add_order_item_meta($item_id, 'label', WC()->cart->tax->get_rate_label($key));
             wc_add_order_item_meta($item_id, 'compound', absint(WC()->cart->tax->is_compound($key) ? 1 : 0));
             wc_add_order_item_meta($item_id, 'tax_amount', wc_format_decimal(isset(WC()->cart->taxes[$key]) ? WC()->cart->taxes[$key] : 0));
             wc_add_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal(isset(WC()->cart->shipping_taxes[$key]) ? WC()->cart->shipping_taxes[$key] : 0));
         }
     }
     // Store coupons
     if ($applied_coupons = WC()->cart->get_coupons()) {
         foreach ($applied_coupons as $code => $coupon) {
             $item_id = wc_add_order_item($order_id, array('order_item_name' => $code, 'order_item_type' => 'coupon'));
             // Add line item meta
             if ($item_id) {
                 wc_add_order_item_meta($item_id, 'discount_amount', isset(WC()->cart->coupon_discount_amounts[$code]) ? WC()->cart->coupon_discount_amounts[$code] : 0);
             }
         }
     }
     if ($this->payment_method) {
         update_post_meta($order_id, '_payment_method', $this->payment_method->id);
         update_post_meta($order_id, '_payment_method_title', $this->payment_method->get_title());
     }
     if (empty($this->posted['billing_email']) && is_user_logged_in()) {
         $current_user = wp_get_current_user();
         update_post_meta($order_id, '_billing_email', $current_user->user_email);
     }
     update_post_meta($order_id, '_order_shipping', wc_format_decimal(WC()->cart->shipping_total));
     update_post_meta($order_id, '_order_discount', wc_format_decimal(WC()->cart->get_order_discount_total()));
     update_post_meta($order_id, '_cart_discount', wc_format_decimal(WC()->cart->get_cart_discount_total()));
     update_post_meta($order_id, '_order_tax', wc_format_decimal(wc_round_tax_total(WC()->cart->tax_total)));
     update_post_meta($order_id, '_order_shipping_tax', wc_format_decimal(wc_round_tax_total(WC()->cart->shipping_tax_total)));
     update_post_meta($order_id, '_order_total', wc_format_decimal(WC()->cart->total, get_option('woocommerce_price_num_decimals')));
     update_post_meta($order_id, '_order_key', 'wc_' . apply_filters('woocommerce_generate_order_key', uniqid('order_')));
     update_post_meta($order_id, '_customer_user', absint($this->customer_id));
     update_post_meta($order_id, '_order_currency', get_woocommerce_currency());
     update_post_meta($order_id, '_prices_include_tax', get_option('woocommerce_prices_include_tax'));
     update_post_meta($order_id, '_customer_ip_address', isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);
     update_post_meta($order_id, '_customer_user_agent', isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
     // Let plugins add meta
     do_action('woocommerce_checkout_update_order_meta', $order_id, $this->posted);
     // Order status
     wp_set_object_terms($order_id, 'pending', 'shop_order_status');
     return $order_id;
 }
/**
 * Update recurring tax for subscriptions
 * Not executed if Subscriptions plugin is not active
 *
 * @since 4.4
 * @return void
 */
function wootax_update_recurring_tax()
{
    global $wpdb;
    // Exit if subs is not active
    if (!WT_SUBS_ACTIVE) {
        return;
    }
    // Find date/time 12 hours from now
    $twelve_hours = mktime(date('H') + 12);
    $date = new DateTime(date('c', $twelve_hours));
    $date = $date->format('Y-m-d H:i:s');
    // Set up logger
    $logger = false;
    if (WT_LOG_REQUESTS) {
        $logger = class_exists('WC_Logger') ? new WC_Logger() : WC()->logger();
        $logger->add('wootax', 'Starting recurring tax update. Subscriptions with payments due before ' . $date . ' are being considered.');
    }
    // Get all scheduled "scheduled_subscription_payment" actions with post_date <= $twelve_hours
    $scheduled = $wpdb->get_results($wpdb->prepare("SELECT ID, post_content FROM {$wpdb->posts} WHERE post_status = %s AND post_title = %s AND post_date <= %s", "pending", "scheduled_subscription_payment", $date));
    // Update recurring totals if necessary
    if (count($scheduled) > 0) {
        // This will hold any warning messages that need to be sent to the admin
        $warnings = array();
        foreach ($scheduled as $action) {
            $temp_warnings = array();
            $show_warnings = false;
            // Run json_decode on post_content to extract user_id and subscription_key
            $args = json_decode($action->post_content);
            // Parse subscription_key to get order_id/product_id (format: ORDERID_PRODUCTID)
            $subscription_key = $args->subscription_key;
            $key_parts = explode('_', $subscription_key);
            $order_id = (int) $key_parts[0];
            $product_id = (int) $key_parts[1];
            if (get_post_status($order_id) == false) {
                continue;
                // Skip if the order no longer exists
            }
            // Determine if changes to subscription amounts are allowed by the current gateway
            $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($order_id, '_recurring_payment_method', true));
            $manual_renewal = WC_Subscriptions_Order::requires_manual_renewal($order_id);
            $changes_supported = $chosen_gateway === false || $manual_renewal == 'true' || $chosen_gateway->supports('subscription_amount_changes') ? true : false;
            // Load order
            $order = WT_Orders::get_order($order_id);
            // Collect data for Lookup request
            $item_data = $type_array = array();
            // Add subscription
            $product = WC_Subscriptions::get_product($product_id);
            // Get order item ID
            $item_id = $wpdb->get_var("SELECT i.order_item_id FROM {$wpdb->prefix}woocommerce_order_items i LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON im.order_item_id = i.order_item_id WHERE im.meta_key = '_product_id' AND im.meta_value = {$product_id} AND i.order_id = {$order_id}");
            // Get price
            $recurring_subtotal = $order->get_item_meta($item_id, '_recurring_line_subtotal');
            $regular_subtotal = $order->get_item_meta($item_id, '_line_subtotal');
            $price = $recurring_subtotal === '0' || !empty($recurring_subtotal) ? $recurring_subtotal : $regular_subtotal;
            // Special case: If _subscription_sign_up_fee is set and $price is equal to its value, fall back to product price
            if ($order->get_item_meta($item_id, '_subscription_sign_up_fee') == $price) {
                $price = $product->get_price();
            }
            $item_info = array('Index' => '', 'ItemID' => $item_id, 'Qty' => 1, 'Price' => $price, 'Type' => 'cart');
            $tic = get_post_meta($product_id, 'wootax_tic', true);
            if (!empty($tic) && $tic) {
                $item_info['TIC'] = $tic;
            }
            $item_data[] = $item_info;
            $type_array[$item_id] = 'cart';
            // Add recurring shipping items
            foreach ($order->order->get_items('recurring_shipping') as $item_id => $shipping) {
                $item_data[] = array('Index' => '', 'ItemID' => $item_id, 'TIC' => WT_SHIPPING_TIC, 'Qty' => 1, 'Price' => $shipping['cost'], 'Type' => 'shipping');
                $type_array[$item_id] = 'shipping';
            }
            // Reset "captured" meta so lookup always sent
            $captured = WT_Orders::get_meta($order_id, 'captured');
            WT_Orders::update_meta($order_id, 'captured', false);
            // Issue Lookup request
            $res = $order->do_lookup($item_data, $type_array, true);
            // Set "captured" back to original value
            WT_Orders::update_meta($order_id, 'captured', $captured);
            // If lookup is successful, use result to update recurring tax totals as described here: http://docs.woothemes.com/document/subscriptions/add-or-modify-a-subscription/#change-recurring-total
            if (is_array($res)) {
                // Find recurring tax item and determine original tax/shipping tax totals
                $wootax_item_id = $wpdb->get_var($wpdb->prepare("SELECT i.order_item_id FROM {$wpdb->prefix}woocommerce_order_items i LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON im.order_item_id = i.order_item_id WHERE im.meta_key = %s AND im.meta_value = %d AND i.order_id = %d AND i.order_item_type = %s", "rate_id", WT_RATE_ID, $order_id, "recurring_tax"));
                $old_tax = empty($wootax_item_id) ? 0 : $order->get_item_meta($wootax_item_id, 'tax_amount');
                $old_shipping_tax = empty($wootax_item_id) ? 0 : $order->get_item_meta($wootax_item_id, 'shipping_tax_amount');
                // Find new tax/shipping tax totals
                // Update _recurring_line_tax meta for each item
                $tax = $shipping_tax = 0;
                foreach ($res as $item) {
                    $item_id = $item->ItemID;
                    $item_tax = $item->TaxAmount;
                    if ($type_array[$item_id] == 'shipping') {
                        $shipping_tax += $item_tax;
                    } else {
                        $tax += $item_tax;
                    }
                    if ($changes_supported) {
                        wc_update_order_item_meta($item_id, '_recurring_line_tax', $item_tax);
                        wc_update_order_item_meta($item_id, '_recurring_line_subtotal_tax', $item_tax);
                    } else {
                        $temp_warnings[] = 'Recurring tax for item #' . $item_id . ' changed to ' . wc_round_tax_total($item_tax);
                    }
                }
                // Update recurring tax if necessary
                if ($old_tax != $tax || $old_shipping_tax != $shipping_tax) {
                    if ($changes_supported) {
                        if (!empty($wootax_item_id)) {
                            wc_update_order_item_meta($wootax_item_id, 'tax_amount', $tax);
                            wc_update_order_item_meta($wootax_item_id, 'cart_tax', $tax);
                            wc_update_order_item_meta($wootax_item_id, 'shipping_tax_amount', $shipping_tax);
                            wc_update_order_item_meta($wootax_item_id, 'shipping_tax', $shipping_tax);
                        }
                        // Determine rounded difference in old/new tax totals
                        $tax_diff = $tax + $shipping_tax - ($old_tax + $old_shipping_tax);
                        $rounded_tax_diff = wc_round_tax_total($tax_diff);
                        // Set new recurring total by adding difference between old and new tax to existing total
                        $new_recurring_total = get_post_meta($order_id, '_order_recurring_total', true) + $rounded_tax_diff;
                        update_post_meta($order_id, '_order_recurring_total', $new_recurring_total);
                        if ($logger) {
                            $logger->add('wootax', 'Set recurring total for order ' . $order_id . ' to: ' . $new_recurring_total);
                        }
                    } else {
                        $temp_warnings[] = 'Total recurring tax changed from ' . wc_round_tax_total($old_tax) . ' to ' . wc_round_tax_total($tax);
                        $temp_warnings[] = 'Total recurring shipping tax changed from ' . wc_round_tax_total($old_shipping_tax) . ' to ' . wc_round_tax_total($shipping_tax);
                        $show_warnings = true;
                    }
                }
                // Add to warnings array if necessary
                if ($show_warnings) {
                    $warnings[$order_id] = $temp_warnings;
                }
            }
        }
        // Send out a single warning email to the admin if necessary
        // Ex: Email sent if a change in tax rates is detected and the gateway used by an order doesn't allow modification of sub. details
        if (count($warnings) > 0) {
            $email = wootax_get_notification_email();
            if (!empty($email) && is_email($email)) {
                $subject = 'WooTax Warning: Recurring Tax Totals Need To Be Updated';
                $message = 'Hello,' . "\r\n\r\n" . 'During a routine check on ' . date('m/d/Y') . ', WooTax discovered ' . count($warnings) . ' subscription orders whose recurring tax totals need to be updated. Unfortunately, the payment gateway(s) used for these orders does not allow subscription details to be altered, so the required changes must be implemented manually. All changes are listed below for your convenience.' . "\r\n\r\n";
                foreach ($warnings as $order_id => $errors) {
                    $message .= 'Order ' . $order_id . ': ' . "\r\n\r\n";
                    foreach ($errors as $error) {
                        $message .= '- ' . $error . "\r\n";
                    }
                    $message .= "\r\n\r\n";
                }
                $message .= 'For assistance, please contact the WooTax support team at sales@wootax.com.';
                wp_mail($email, $subject, $message);
            }
        }
    } else {
        if ($logger) {
            $logger->add('wootax', 'Ending recurring tax update. No subscriptions due before ' . $date . '.');
        }
    }
}
 /**
  * Sets up the express checkout transaction
  *
  * @link https://developer.paypal.com/docs/classic/express-checkout/integration-guide/ECGettingStarted/#id084RN060BPF
  * @link https://developer.paypal.com/webapps/developer/docs/classic/api/merchant/SetExpressCheckout_API_Operation_NVP/
  *
  * @since 3.0.0
  * @param array $args {
  *     @type string $return_url                URL to which the buyer's browser is returned after choosing to pay with PayPal.
  *     @type string $cancel_url                URL to which the buyer is returned if the buyer does not approve the use of PayPal to pay.
  *     @type string $page_style                Name of the Custom Payment Page Style for payment pages associated with this button or link.
  *     @type bool   $use_bml                   Whether to use Bill Me Later or not, defaults to false.
  *     @type bool   $paypal_account_optional   Whether using/having a PayPal account is optional or not.
  *     @type string $landing_page              PayPal landing page to use, defaults to `billing`.
  * }
  */
 public function set_express_checkout($args)
 {
     $this->set_method('SetExpressCheckout');
     $defaults = array('use_bml' => false, 'paypal_account_optional' => false, 'landing_page' => 'billing', 'page_style' => null, 'brand_name' => null, 'payment_action' => self::AUTH_CAPTURE);
     $args = wp_parse_args($args, $defaults);
     $this->add_parameters(array('RETURNURL' => $args['return_url'], 'CANCELURL' => $args['cancel_url'], 'PAGESTYLE' => $args['page_style'], 'BRANDNAME' => $args['brand_name'], 'SOLUTIONTYPE' => $args['paypal_account_optional'] ? 'Sole' : 'Mark', 'LANDINGPAGE' => 'login' == $args['landing_page'] ? 'Login' : 'Billing'));
     // override params specific to BML
     if ($args['use_bml']) {
         $this->add_parameters(array('USERSELECTEDFUNDINGSOURCE' => 'BML', 'SOLUTIONTYPE' => 'Sole', 'LANDINGPAGE' => 'Billing'));
     }
     // item count
     $i = 0;
     // force total calculation
     if (!defined('WOOCOMMERCE_CART')) {
         define('WOOCOMMERCE_CART', true);
     }
     WC()->cart->calculate_totals();
     if ($this->skip_line_items()) {
         $item_names = array();
         foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
             $product = apply_filters('woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key);
             $quantity = absint($cart_item['quantity']);
             $item_names[] = sprintf('%s x %s', $product->get_title(), $quantity);
         }
         // add fees
         foreach (WC()->cart->get_fees() as $fee) {
             $item_names[] = sprintf(__('Fee - %s', WC_PayPal_Express::TEXT_DOMAIN), $fee->name);
         }
         $cart_discount = SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3() ? 0 : WC()->cart->get_order_discount_total();
         // cart_contents_total includes pre-tax discounts in 2.3
         $this->add_line_item_parameters(array('NAME' => sprintf(__('%s - Order', WC_PayPal_Express::TEXT_DOMAIN), get_option('blogname')), 'DESC' => SV_WC_Helper::str_truncate(html_entity_decode(implode(', ', $item_names), ENT_QUOTES, 'UTF-8'), 127), 'AMT' => WC()->cart->cart_contents_total + WC()->cart->fee_total - $cart_discount + WC()->cart->tax_total), 0);
         // set order-level totals
         //  - Do not send the TAXAMT due to rounding errors
         $this->add_payment_parameters(array('AMT' => WC()->cart->total, 'CURRENCYCODE' => get_woocommerce_currency(), 'ITEMAMT' => WC()->cart->cart_contents_total + WC()->cart->fee_total - $cart_discount + WC()->cart->tax_total, 'SHIPPINGAMT' => WC()->cart->shipping_total + WC()->cart->shipping_tax_total, 'PAYMENTACTION' => $args['payment_action'] == self::AUTH_ONLY ? self::AUTH_ONLY : self::AUTH_CAPTURE));
     } else {
         // add line items
         foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
             $product = apply_filters('woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key);
             $quantity = absint($cart_item['quantity']);
             $this->add_line_item_parameters(array('NAME' => SV_WC_Helper::str_truncate(html_entity_decode($product->get_title(), ENT_QUOTES, 'UTF-8'), 127), 'DESC' => $this->get_item_description($cart_item, $product), 'AMT' => round($cart_item['line_subtotal'] / $quantity, 2), 'QTY' => $quantity, 'ITEMURL' => $product->get_permalink()), $i++);
             // note: TAXAMT is skipped as PayPal doesn't display the per-item
             // tax amount to the customer, and it breaks totals calculations with
             // pre-tax discounts. The total order tax is included instead.
         }
         if (SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3()) {
             // WC 2.3+, no after-tax discounts
             if (WC()->cart->get_cart_discount_total() > 0) {
                 $this->add_line_item_parameters(array('NAME' => __('Total Discount', WC_Paypal_Express::TEXT_DOMAIN), 'QTY' => 1, 'AMT' => -WC()->cart->get_cart_discount_total()), $i++);
             }
         } else {
             // WC 2.2 or lesser
             // add cart discounts as line item
             if (WC()->cart->get_cart_discount_total() > 0) {
                 $this->add_line_item_parameters(array('NAME' => __('Cart Discount', WC_Paypal_Express::TEXT_DOMAIN), 'QTY' => 1, 'AMT' => -WC()->cart->get_cart_discount_total()), $i++);
             }
             // add order discounts as line item
             if (WC()->cart->get_order_discount_total() > 0) {
                 $this->add_line_item_parameters(array('NAME' => __('Order Discount', WC_Paypal_Express::TEXT_DOMAIN), 'QTY' => 1, 'AMT' => -WC()->cart->get_order_discount_total()), $i);
             }
         }
         // add fees
         foreach (WC()->cart->get_fees() as $fee) {
             $this->add_line_item_parameters(array('NAME' => __('Fee', WC_Paypal_Express::TEXT_DOMAIN), 'DESC' => SV_WC_Helper::str_truncate($fee->name, 127), 'AMT' => $fee->amount, 'QTY' => 1), $i++);
         }
         // set order-level totals
         $this->add_payment_parameters(array('AMT' => WC()->cart->total, 'CURRENCYCODE' => get_woocommerce_currency(), 'ITEMAMT' => WC()->cart->cart_contents_total + WC()->cart->fee_total - (SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3() ? 0 : WC()->cart->get_order_discount_total()), 'SHIPPINGAMT' => WC()->cart->shipping_total, 'TAXAMT' => wc_round_tax_total(WC()->cart->tax_total + WC()->cart->shipping_tax_total), 'PAYMENTACTION' => $args['payment_action'] == self::AUTH_ONLY ? self::AUTH_ONLY : self::AUTH_CAPTURE));
     }
     // set max amount to 150% of the total to allow for increases in shipping, etc. before final checkout
     $this->add_parameter('MAXAMT', WC()->cart->total + WC()->cart->total * 0.5);
     // set customer shipping name and address
     if (is_user_logged_in()) {
         $customer_id = get_current_user_id();
         $this->add_payment_parameters(array('SHIPTONAME' => get_user_meta($customer_id, 'shipping_first_name', true) . ' ' . get_user_meta($customer_id, 'shipping_last_name', true)));
     }
     $this->add_payment_parameters(array('SHIPTOSTREET' => WC()->customer->get_shipping_address(), 'SHIPTOSTREET2' => WC()->customer->get_shipping_address_2(), 'SHIPTOCITY' => WC()->customer->get_shipping_city(), 'SHIPTOSTATE' => WC()->customer->get_shipping_state(), 'SHIPTOZIP' => WC()->customer->get_shipping_postcode(), 'SHIPTOCOUNTRYCODE' => WC()->customer->get_shipping_country()));
 }
示例#17
0
 /**
  * Test wc_round_tax_total().
  *
  * Note the PHP 5.2 section of wc_round_tax_total() is excluded from test.
  * coverage.
  *
  * @since 2.2
  */
 public function test_wc_round_tax_total()
 {
     $this->assertEquals(1.25, wc_round_tax_total(1.246));
     $this->assertEquals(20, wc_round_tax_total(19.9997));
     $this->assertEquals(19.99, wc_round_tax_total(19.99));
 }
 /**
  * Save meta box data
  */
 public static function save($post_id, $post)
 {
     global $wpdb;
     // Save tax rows
     $total_tax = 0;
     $total_shipping_tax = 0;
     if (isset($_POST['order_taxes_id'])) {
         $get_values = array('order_taxes_id', 'order_taxes_rate_id', 'order_taxes_amount', 'order_taxes_shipping_amount');
         foreach ($get_values as $value) {
             ${$value} = isset($_POST[$value]) ? $_POST[$value] : array();
         }
         foreach ($order_taxes_id as $item_id => $value) {
             if ($item_id == 'new') {
                 foreach ($value as $new_key => $new_value) {
                     $rate_id = absint($order_taxes_rate_id[$item_id][$new_key]);
                     if ($rate_id) {
                         $rate = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $rate_id));
                         $label = $rate->tax_rate_name ? $rate->tax_rate_name : WC()->countries->tax_or_vat();
                         $compound = $rate->tax_rate_compound ? 1 : 0;
                         $code = array();
                         $code[] = $rate->tax_rate_country;
                         $code[] = $rate->tax_rate_state;
                         $code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
                         $code[] = absint($rate->tax_rate_priority);
                         $code = strtoupper(implode('-', array_filter($code)));
                     } else {
                         $code = '';
                         $label = WC()->countries->tax_or_vat();
                     }
                     // Add line item
                     $new_id = wc_add_order_item($post_id, array('order_item_name' => wc_clean($code), 'order_item_type' => 'tax'));
                     // Add line item meta
                     if ($new_id) {
                         wc_update_order_item_meta($new_id, 'rate_id', $rate_id);
                         wc_update_order_item_meta($new_id, 'label', $label);
                         wc_update_order_item_meta($new_id, 'compound', $compound);
                         if (isset($order_taxes_amount[$item_id][$new_key])) {
                             wc_update_order_item_meta($new_id, 'tax_amount', wc_format_decimal($order_taxes_amount[$item_id][$new_key]));
                             $total_tax += wc_format_decimal($order_taxes_amount[$item_id][$new_key]);
                         }
                         if (isset($order_taxes_shipping_amount[$item_id][$new_key])) {
                             wc_update_order_item_meta($new_id, 'shipping_tax_amount', wc_format_decimal($order_taxes_shipping_amount[$item_id][$new_key]));
                             $total_shipping_tax += wc_format_decimal($order_taxes_shipping_amount[$item_id][$new_key]);
                         }
                     }
                 }
             } else {
                 $item_id = absint($item_id);
                 $rate_id = absint($order_taxes_rate_id[$item_id]);
                 if ($rate_id) {
                     $rate = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $rate_id));
                     $label = $rate->tax_rate_name ? $rate->tax_rate_name : WC()->countries->tax_or_vat();
                     $compound = $rate->tax_rate_compound ? 1 : 0;
                     $code = array();
                     $code[] = $rate->tax_rate_country;
                     $code[] = $rate->tax_rate_state;
                     $code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
                     $code[] = absint($rate->tax_rate_priority);
                     $code = strtoupper(implode('-', array_filter($code)));
                 } else {
                     $code = '';
                     $label = WC()->countries->tax_or_vat();
                 }
                 $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => wc_clean($code)), array('order_item_id' => $item_id), array('%s'), array('%d'));
                 wc_update_order_item_meta($item_id, 'rate_id', $rate_id);
                 wc_update_order_item_meta($item_id, 'label', $label);
                 wc_update_order_item_meta($item_id, 'compound', $compound);
                 if (isset($order_taxes_amount[$item_id])) {
                     wc_update_order_item_meta($item_id, 'tax_amount', wc_format_decimal($order_taxes_amount[$item_id]));
                     $total_tax += wc_format_decimal($order_taxes_amount[$item_id]);
                 }
                 if (isset($order_taxes_shipping_amount[$item_id])) {
                     wc_update_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal($order_taxes_shipping_amount[$item_id]));
                     $total_shipping_tax += wc_format_decimal($order_taxes_shipping_amount[$item_id]);
                 }
             }
         }
     }
     // Update totals
     update_post_meta($post_id, '_order_tax', wc_round_tax_total($total_tax));
     update_post_meta($post_id, '_order_shipping_tax', wc_round_tax_total($total_shipping_tax));
     update_post_meta($post_id, '_order_discount', wc_format_decimal($_POST['_order_discount']));
     update_post_meta($post_id, '_order_total', wc_format_decimal($_POST['_order_total']));
     // Shipping Rows
     $order_shipping = 0;
     if (isset($_POST['shipping_method_id'])) {
         $get_values = array('shipping_method_id', 'shipping_method_title', 'shipping_method', 'shipping_cost');
         foreach ($get_values as $value) {
             ${$value} = isset($_POST[$value]) ? $_POST[$value] : array();
         }
         foreach ($shipping_method_id as $item_id => $value) {
             if ($item_id == 'new') {
                 foreach ($value as $new_key => $new_value) {
                     $method_id = wc_clean($shipping_method[$item_id][$new_key]);
                     $method_title = wc_clean($shipping_method_title[$item_id][$new_key]);
                     $cost = wc_format_decimal($shipping_cost[$item_id][$new_key]);
                     $new_id = wc_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'shipping'));
                     if ($new_id) {
                         wc_add_order_item_meta($new_id, 'method_id', $method_id);
                         wc_add_order_item_meta($new_id, 'cost', $cost);
                     }
                     $order_shipping += $cost;
                 }
             } else {
                 $item_id = absint($item_id);
                 $method_id = wc_clean($shipping_method[$item_id]);
                 $method_title = wc_clean($shipping_method_title[$item_id]);
                 $cost = wc_format_decimal($shipping_cost[$item_id]);
                 $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => $method_title), array('order_item_id' => $item_id), array('%s'), array('%d'));
                 wc_update_order_item_meta($item_id, 'method_id', $method_id);
                 wc_update_order_item_meta($item_id, 'cost', $cost);
                 $order_shipping += $cost;
             }
         }
     }
     // Delete rows
     if (isset($_POST['delete_order_item_id'])) {
         $delete_ids = $_POST['delete_order_item_id'];
         foreach ($delete_ids as $id) {
             wc_delete_order_item(absint($id));
         }
     }
     delete_post_meta($post_id, '_shipping_method');
     delete_post_meta($post_id, '_shipping_method_title');
     update_post_meta($post_id, '_order_shipping', $order_shipping);
 }
    /**
     * Get the main chart.
     *
     * @return string
     */
    public function get_main_chart()
    {
        global $wpdb;
        $query_data = array('order_item_name' => array('type' => 'order_item', 'function' => '', 'name' => 'tax_rate'), 'tax_amount' => array('type' => 'order_item_meta', 'order_item_type' => 'tax', 'function' => '', 'name' => 'tax_amount'), 'shipping_tax_amount' => array('type' => 'order_item_meta', 'order_item_type' => 'tax', 'function' => '', 'name' => 'shipping_tax_amount'), 'rate_id' => array('type' => 'order_item_meta', 'order_item_type' => 'tax', 'function' => '', 'name' => 'rate_id'), 'ID' => array('type' => 'post_data', 'function' => '', 'name' => 'post_id'));
        $query_where = array(array('key' => 'order_item_type', 'value' => 'tax', 'operator' => '='), array('key' => 'order_item_name', 'value' => '', 'operator' => '!='));
        $tax_rows_orders = $this->get_order_report_data(array('data' => $query_data, 'where' => $query_where, 'order_by' => 'posts.post_date ASC', 'query_type' => 'get_results', 'filter_range' => true, 'order_types' => array_merge(wc_get_order_types('sales-reports'), array('shop_order_refund')), 'order_status' => array('completed', 'processing', 'on-hold'), 'parent_order_status' => array('completed', 'processing', 'on-hold')));
        // Merge
        $tax_rows = array();
        foreach ($tax_rows_orders as $tax_row) {
            $key = $tax_row->rate_id;
            $tax_rows[$key] = isset($tax_rows[$key]) ? $tax_rows[$key] : (object) array('tax_amount' => 0, 'shipping_tax_amount' => 0, 'total_orders' => 0);
            if ('shop_order_refund' !== get_post_type($tax_row->post_id)) {
                $tax_rows[$key]->total_orders += 1;
            }
            $tax_rows[$key]->tax_rate = $tax_row->tax_rate;
            $tax_rows[$key]->tax_amount += wc_round_tax_total($tax_row->tax_amount);
            $tax_rows[$key]->shipping_tax_amount += wc_round_tax_total($tax_row->shipping_tax_amount);
        }
        ?>
		<table class="widefat">
			<thead>
				<tr>
					<th><?php 
        _e('Tax', 'woocommerce');
        ?>
</th>
					<th><?php 
        _e('Rate', 'woocommerce');
        ?>
</th>
					<th class="total_row"><?php 
        _e('Number of Orders', 'woocommerce');
        ?>
</th>
					<th class="total_row"><?php 
        _e('Tax Amount', 'woocommerce');
        ?>
 <?php 
        echo wc_help_tip(__('This is the sum of the "Tax Rows" tax amount within your orders.', 'woocommerce'));
        ?>
</th>
					<th class="total_row"><?php 
        _e('Shipping Tax Amount', 'woocommerce');
        ?>
 <?php 
        echo wc_help_tip(__('This is the sum of the "Tax Rows" shipping tax amount within your orders.', 'woocommerce'));
        ?>
</th>
					<th class="total_row"><?php 
        _e('Total Tax', 'woocommerce');
        ?>
 <?php 
        echo wc_help_tip(__('This is the total tax for the rate (shipping tax + product tax).', 'woocommerce'));
        ?>
</th>
				</tr>
			</thead>
			<?php 
        if ($tax_rows) {
            ?>
				<tbody>
					<?php 
            foreach ($tax_rows as $rate_id => $tax_row) {
                $rate = $wpdb->get_var($wpdb->prepare("SELECT tax_rate FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id));
                ?>
						<tr>
							<th scope="row"><?php 
                echo apply_filters('woocommerce_reports_taxes_tax_rate', $tax_row->tax_rate, $rate_id, $tax_row);
                ?>
</th>
							<td><?php 
                echo apply_filters('woocommerce_reports_taxes_rate', $rate, $rate_id, $tax_row);
                ?>
%</td>
							<td class="total_row"><?php 
                echo $tax_row->total_orders;
                ?>
</td>
							<td class="total_row"><?php 
                echo wc_price($tax_row->tax_amount);
                ?>
</td>
							<td class="total_row"><?php 
                echo wc_price($tax_row->shipping_tax_amount);
                ?>
</td>
							<td class="total_row"><?php 
                echo wc_price($tax_row->tax_amount + $tax_row->shipping_tax_amount);
                ?>
</td>
						</tr>
						<?php 
            }
            ?>
				</tbody>
				<tfoot>
					<tr>
						<th scope="row" colspan="3"><?php 
            _e('Total', 'woocommerce');
            ?>
</th>
						<th class="total_row"><?php 
            echo wc_price(wc_round_tax_total(array_sum(wp_list_pluck((array) $tax_rows, 'tax_amount'))));
            ?>
</th>
						<th class="total_row"><?php 
            echo wc_price(wc_round_tax_total(array_sum(wp_list_pluck((array) $tax_rows, 'shipping_tax_amount'))));
            ?>
</th>
						<th class="total_row"><strong><?php 
            echo wc_price(wc_round_tax_total(array_sum(wp_list_pluck((array) $tax_rows, 'tax_amount')) + array_sum(wp_list_pluck((array) $tax_rows, 'shipping_tax_amount'))));
            ?>
</strong></th>
					</tr>
				</tfoot>
			<?php 
        } else {
            ?>
				<tbody>
					<tr>
						<td><?php 
            _e('No taxes found in this period', 'woocommerce');
            ?>
</td>
					</tr>
				</tbody>
			<?php 
        }
        ?>
		</table>
		<?php 
    }
 /**
  * Get tax row amounts with or without compound taxes includes.
  * @param  boolean $compound True if getting compound taxes
  * @param  boolean $display  True if getting total to display
  * @return float price
  */
 public function get_taxes_total($compound = true, $display = true)
 {
     $total = 0;
     foreach ($this->taxes as $key => $tax) {
         if (!$compound && $this->tax->is_compound($key)) {
             continue;
         }
         $total += $tax;
     }
     foreach ($this->shipping_taxes as $key => $tax) {
         if (!$compound && $this->tax->is_compound($key)) {
             continue;
         }
         $total += $tax;
     }
     if ($display) {
         return wc_round_tax_total($total);
     } else {
         return $total;
     }
 }
示例#21
0
if (!empty($tax_data)) {
    foreach ($order_taxes as $tax_item) {
        $tax_item_id = $tax_item['rate_id'];
        $tax_item_total = isset($tax_data['total'][$tax_item_id]) ? $tax_data['total'][$tax_item_id] : '';
        $tax_item_subtotal = isset($tax_data['subtotal'][$tax_item_id]) ? $tax_data['subtotal'][$tax_item_id] : '';
        ?>
				<td class="line_tax" width="1%">
					<div class="view">
						<?php 
        if ('' != $tax_item_total) {
            echo wc_price(wc_round_tax_total($tax_item_total), array('currency' => $order->get_order_currency()));
        } else {
            echo '&ndash;';
        }
        if (isset($item['line_subtotal']) && $item['line_subtotal'] !== $item['line_total']) {
            echo '<span class="wc-order-item-discount">-' . wc_price(wc_round_tax_total($tax_item_subtotal - $tax_item_total), array('currency' => $order->get_order_currency())) . '</span>';
        }
        if ($refunded = $order->get_tax_refunded_for_item($item_id, $tax_item_id)) {
            echo '<small class="refunded">' . wc_price($refunded, array('currency' => $order->get_order_currency())) . '</small>';
        }
        ?>
					</div>
					<div class="edit" style="display: none;">
						<div class="split-input">
							<div class="input">
								<label><?php 
        esc_attr_e('Pre-discount:', 'woocommerce');
        ?>
</label>
								<input type="text" name="line_subtotal_tax[<?php 
        echo absint($item_id);
			</td>

			<td class="column-total">
				<?php 
    echo isset($item['cost']) ? wc_price(wc_round_tax_total($item['cost'])) : '';
    ?>
			</td>

			<td class="column-tax">
				<?php 
    $taxes = 0;
    $taxes_list = maybe_unserialize($item['taxes']);
    foreach ($taxes_list as $tax_id => $tax_item) {
        $taxes += $tax_item;
    }
    echo wc_price(wc_round_tax_total($taxes));
    ?>
			</td>
		</tr>
	<?php 
}
?>

	</tbody>
</table>

<table>
	<tr>
		<td class="column1">

		</td>
 /**
  * Returns a string of the sum of all taxes in the cart for initial payment and
  * recurring amount.
  *
  * @return array Array of tax_id => tax_amounts for items in the cart
  * @since 1.4.10
  */
 public static function get_taxes_total_html($total)
 {
     if (self::cart_contains_subscription()) {
         $recurring_total = self::get_recurring_taxes_total();
         if (function_exists('wc_round_tax_total')) {
             // WC 2.1
             $recurring_total = wc_round_tax_total($recurring_total);
         }
         $include_trial = woocommerce_price(0) == $total ? true : false;
         $total = self::get_cart_subscription_string($total, $recurring_total, array('include_trial' => $include_trial));
     }
     return $total;
 }
示例#24
0
    echo $this->colspan['left'];
    ?>
"></td>
			<td colspan="<?php 
    echo $this->colspan['right_left'];
    ?>
"><?php 
    echo !empty($item['name']) ? esc_html($item['name']) : __('Fee', 'woocommerce');
    ?>
</td>
			<td colspan="<?php 
    echo $this->colspan['right_right'];
    ?>
" class="align-right">
				<?php 
    echo isset($item['line_total']) ? wc_price(wc_round_tax_total($item['line_total'])) : '';
    if ($refunded = $this->order->get_total_refunded_for_item($item_id, 'fee')) {
        echo '<br/><small class="refunded">-' . wc_price($refunded, array('currency' => $this->order->get_order_currency())) . '</small>';
    }
    ?>
			</td>
		</tr>
	<?php 
}
?>
	<!-- Tax -->
	<?php 
if ($this->template_options['bewpi_show_tax_total'] && wc_tax_enabled()) {
    foreach ($this->order->get_tax_totals() as $code => $tax) {
        ?>
			<tr class="after-products">
示例#25
0
if (empty($legacy_order) && wc_tax_enabled()) {
    $line_tax_data = isset($item['line_tax_data']) ? $item['line_tax_data'] : '';
    $tax_data = maybe_unserialize($line_tax_data);
    foreach ($order_taxes as $tax_item) {
        $tax_item_id = $tax_item['rate_id'];
        $tax_item_total = isset($tax_data['total'][$tax_item_id]) ? $tax_data['total'][$tax_item_id] : '';
        $tax_item_subtotal = isset($tax_data['subtotal'][$tax_item_id]) ? $tax_data['subtotal'][$tax_item_id] : '';
        ?>
					<td class="line_tax" width="1%">
						<div class="view">
							<?php 
        if ('' != $tax_item_total) {
            if (isset($tax_item_subtotal) && $tax_item_subtotal != $tax_item_total) {
                echo '<del>' . wc_price(wc_round_tax_total($tax_item_subtotal), array('currency' => $order->get_order_currency())) . '</del> ';
            }
            echo wc_price(wc_round_tax_total($tax_item_total), array('currency' => $order->get_order_currency()));
        } else {
            echo '&ndash;';
        }
        if ($refunded = $order->get_tax_refunded_for_item($item_id, $tax_item_id)) {
            echo '<small class="refunded">-' . wc_price($refunded, array('currency' => $order->get_order_currency())) . '</small>';
        }
        ?>
						</div>
						<div class="edit" style="display: none;">
							<div class="split-input">
								<?php 
        $item_total_tax = isset($tax_item_total) ? esc_attr(wc_format_localized_price($tax_item_total)) : '';
        ?>
								<input type="text" name="line_tax[<?php 
        echo absint($item_id);
 /**
  * When an order is added or updated from the admin interface, check if a subscription product
  * has been manually added to the order or the details of the subscription have been modified,
  * and create/update the subscription as required.
  *
  * Save subscription order meta items
  *
  * @param int $post_id The ID of the post which is the WC_Order object.
  * @param Object $post The post object of the order.
  * @since 1.1
  */
 public static function pre_process_shop_order_meta($post_id, $post)
 {
     global $woocommerce, $wpdb;
     $order_contains_subscription = false;
     $order = new WC_Order($post_id);
     $existing_product_ids = array();
     foreach ($order->get_items() as $existing_item) {
         $existing_product_ids[] = self::get_items_product_id($existing_item);
     }
     $product_ids = array();
     if (isset($_POST['order_item_id'])) {
         foreach ($_POST['order_item_id'] as $order_item_id) {
             $product_ids[$order_item_id] = woocommerce_get_order_item_meta($order_item_id, '_product_id');
         }
     }
     // Check if there are new subscription products to be added, or the order already has a subscription item
     foreach (array_merge($product_ids, $existing_product_ids) as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's a subscription product, we have a subscription
         if (!$is_existing_item && WC_Subscriptions_Product::is_subscription($product_id)) {
             $order_contains_subscription = true;
         }
         // If this is an existing item and it's a subscription item, we have a subscription
         if ($is_existing_item && self::is_item_subscription($order, $product_id)) {
             $order_contains_subscription = true;
         }
     }
     if (!$order_contains_subscription) {
         return $post_id;
     }
     $existing_payment_method = get_post_meta($post_id, '_recurring_payment_method', true);
     $chosen_payment_method = isset($_POST['_recurring_payment_method']) ? stripslashes($_POST['_recurring_payment_method']) : '';
     // For subscriptions manually added using paypal, make sure the _paypal_first_ipn_ignored_for_pdt is set so that IPN notifications are never ignored
     if (isset($_POST['_payment_method']) && 'paypal' == $_POST['_payment_method'] && 'true' != get_post_meta($post_id, '_paypal_first_ipn_ignored_for_pdt', true)) {
         update_post_meta($post_id, '_paypal_first_ipn_ignored_for_pdt', 'true');
     }
     // If the recurring payment method is changing, or it isn't set make sure we have correct manual payment flag set
     if (isset($_POST['_recurring_payment_method']) || empty($existing_payment_method) && ($chosen_payment_method != $existing_payment_method || empty($chosen_payment_method))) {
         $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
         // Make sure the subscription is cancelled with the current gateway
         if (!empty($existing_payment_method) && isset($payment_gateways[$existing_payment_method]) && $payment_gateways[$existing_payment_method]->supports('subscriptions')) {
             foreach ($product_ids as $product_id) {
                 WC_Subscriptions_Payment_Gateways::trigger_gateway_cancelled_subscription_hook(absint($_POST['customer_user']), WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id));
             }
         }
         if (!empty($chosen_payment_method) && isset($payment_gateways[$chosen_payment_method]) && $payment_gateways[$chosen_payment_method]->supports('subscriptions')) {
             $manual_renewal = 'false';
         } else {
             $manual_renewal = 'true';
         }
         update_post_meta($post_id, '_wcs_requires_manual_renewal', $manual_renewal);
         if (!empty($chosen_payment_method)) {
             update_post_meta($post_id, '_recurring_payment_method', stripslashes($_POST['_recurring_payment_method']));
         }
     }
     // Make sure the recurring order totals are correct
     update_post_meta($post_id, '_order_recurring_discount_total', WC_Subscriptions::format_total($_POST['_order_recurring_discount_total']));
     update_post_meta($post_id, '_order_recurring_total', WC_Subscriptions::format_total($_POST['_order_recurring_total']));
     // Update fields for WC < 2.1
     if (WC_Subscriptions::is_woocommerce_pre('2.1')) {
         // Also allow updates to the recurring payment method's title
         if (isset($_POST['_recurring_payment_method_title'])) {
             update_post_meta($post_id, '_recurring_payment_method_title', stripslashes($_POST['_recurring_payment_method_title']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_recurring_payment_method_title', '');
         }
         if (isset($_POST['_order_recurring_discount_cart'])) {
             update_post_meta($post_id, '_order_recurring_discount_cart', stripslashes($_POST['_order_recurring_discount_cart']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_discount_cart', 0);
         }
         if (isset($_POST['_order_recurring_tax_total'])) {
             // WC < 2.1
             update_post_meta($post_id, '_order_recurring_tax_total', stripslashes($_POST['_order_recurring_tax_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_tax_total', 0);
         }
         if (isset($_POST['_order_recurring_shipping_tax_total'])) {
             update_post_meta($post_id, '_order_recurring_shipping_tax_total', stripslashes($_POST['_order_recurring_shipping_tax_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_shipping_tax_total', 0);
         }
         if (isset($_POST['_order_recurring_shipping_total'])) {
             update_post_meta($post_id, '_order_recurring_shipping_total', stripslashes($_POST['_order_recurring_shipping_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_shipping_total', 0);
         }
     }
     // Save tax rows
     $total_tax = 0;
     $total_shipping_tax = 0;
     if (isset($_POST['recurring_order_taxes_id'])) {
         // WC 2.0+
         $tax_keys = array('recurring_order_taxes_id', 'recurring_order_taxes_rate_id', 'recurring_order_taxes_amount', 'recurring_order_taxes_shipping_amount');
         foreach ($tax_keys as $tax_key) {
             ${$tax_key} = isset($_POST[$tax_key]) ? $_POST[$tax_key] : array();
         }
         foreach ($recurring_order_taxes_id as $item_id => $value) {
             $item_id = absint($item_id);
             $rate_id = absint($recurring_order_taxes_rate_id[$item_id]);
             if ($rate_id) {
                 $rate = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $rate_id));
                 $label = $rate->tax_rate_name ? $rate->tax_rate_name : $woocommerce->countries->tax_or_vat();
                 $compound = $rate->tax_rate_compound ? 1 : 0;
                 $code = array();
                 $code[] = $rate->tax_rate_country;
                 $code[] = $rate->tax_rate_state;
                 $code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
                 $code[] = absint($rate->tax_rate_priority);
                 $code = strtoupper(implode('-', array_filter($code)));
             } else {
                 $code = '';
                 $label = $woocommerce->countries->tax_or_vat();
             }
             $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => woocommerce_clean($code)), array('order_item_id' => $item_id), array('%s'), array('%d'));
             woocommerce_update_order_item_meta($item_id, 'rate_id', $rate_id);
             woocommerce_update_order_item_meta($item_id, 'label', $label);
             woocommerce_update_order_item_meta($item_id, 'compound', $compound);
             if (isset($recurring_order_taxes_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'tax_amount', WC_Subscriptions::format_total($recurring_order_taxes_amount[$item_id]));
                 $total_tax += WC_Subscriptions::format_total($recurring_order_taxes_amount[$item_id]);
             }
             if (isset($recurring_order_taxes_shipping_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'shipping_tax_amount', WC_Subscriptions::format_total($recurring_order_taxes_shipping_amount[$item_id]));
                 $total_shipping_tax += WC_Subscriptions::format_total($recurring_order_taxes_shipping_amount[$item_id]);
             }
         }
     }
     if (!isset($_POST['_order_recurring_tax_total']) && function_exists('wc_round_tax_total')) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_tax_total', wc_round_tax_total($total_tax));
     }
     if (!isset($_POST['_order_recurring_shipping_tax_total']) && function_exists('wc_round_tax_total')) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_shipping_tax_total', wc_round_tax_total($total_shipping_tax));
     }
     // And that shipping methods are updated as required
     if (isset($_POST['_recurring_shipping_method']) || isset($_POST['_recurring_shipping_method_title'])) {
         // WC < 2.1
         update_post_meta($post_id, '_recurring_shipping_method', stripslashes($_POST['_recurring_shipping_method']));
         update_post_meta($post_id, '_recurring_shipping_method_title', stripslashes($_POST['_recurring_shipping_method_title']));
     }
     // Shipping Rows
     $recurring_order_shipping = 0;
     if (isset($_POST['recurring_shipping_method_id'])) {
         // WC 2.1+
         $get_values = array('recurring_shipping_method_id', 'recurring_shipping_method_title', 'recurring_shipping_method', 'recurring_shipping_cost');
         foreach ($get_values as $value) {
             ${$value} = isset($_POST[$value]) ? $_POST[$value] : array();
         }
         foreach ($recurring_shipping_method_id as $item_id => $value) {
             if ('new' == $item_id) {
                 foreach ($value as $new_key => $new_value) {
                     $method_id = woocommerce_clean($recurring_shipping_method[$item_id][$new_key]);
                     $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id][$new_key]);
                     $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id][$new_key]);
                     $new_id = woocommerce_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'recurring_shipping'));
                     if ($new_id) {
                         woocommerce_add_order_item_meta($new_id, 'method_id', $method_id);
                         woocommerce_add_order_item_meta($new_id, 'cost', $cost);
                     }
                     $recurring_order_shipping += $cost;
                 }
             } elseif ('old' == $item_id) {
                 // Migrate a WC 2.0.n shipping method to WC 2.1 format
                 $method_id = woocommerce_clean($recurring_shipping_method[$item_id]);
                 $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id]);
                 $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id]);
                 $new_id = woocommerce_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'recurring_shipping'));
                 if ($new_id) {
                     woocommerce_add_order_item_meta($new_id, 'method_id', $method_id);
                     woocommerce_add_order_item_meta($new_id, 'cost', $cost);
                 }
                 $recurring_order_shipping += $cost;
                 delete_post_meta($post_id, '_recurring_shipping_method');
                 delete_post_meta($post_id, '_recurring_shipping_method_title');
             } else {
                 $item_id = absint($item_id);
                 $method_id = woocommerce_clean($recurring_shipping_method[$item_id]);
                 $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id]);
                 $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id]);
                 $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => $method_title), array('order_item_id' => $item_id), array('%s'), array('%d'));
                 woocommerce_update_order_item_meta($item_id, 'method_id', $method_id);
                 woocommerce_update_order_item_meta($item_id, 'cost', $cost);
                 $recurring_order_shipping += $cost;
             }
         }
     }
     if (!isset($_POST['_order_recurring_shipping_total'])) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_shipping_total', $recurring_order_shipping);
     }
     // Check if all the subscription products on the order have associated subscriptions on the user's account, and if not, add a new one
     foreach ($product_ids as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's not a subscription product, ignore it
         if (!$is_existing_item && !WC_Subscriptions_Product::is_subscription($product_id)) {
             continue;
         }
         // If this is an existing item and it's not a subscription, ignore it
         if ($is_existing_item && !self::is_item_subscription($order, $product_id)) {
             continue;
         }
         $subscription_key = WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id);
         $subscription = array();
         if (!empty($order->customer_user) && $_POST['customer_user'] != $order->customer_user) {
             $customer_has_changed = true;
             $hook_args = array('user_id' => (int) $order->customer_user, 'subscription_key' => $subscription_key);
             wc_unschedule_action('scheduled_subscription_trial_end', $hook_args);
             wc_unschedule_action('scheduled_subscription_payment', $hook_args);
             wc_unschedule_action('scheduled_subscription_expiration', $hook_args);
         } else {
             $customer_has_changed = false;
         }
         // In case it's a new order or the customer has changed
         $order->customer_user = $order->user_id = (int) $_POST['customer_user'];
         $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key);
         if (empty($subscription)) {
             // Add a new subscription
             // The order may not exist yet, so we need to set a few things ourselves
             if (empty($order->order_key)) {
                 $order->order_key = uniqid('order_');
                 add_post_meta($post_id, '_order_key', $order->order_key, true);
             }
             if (empty($_POST['order_date'])) {
                 $start_date = gmdate('Y-m-d H:i:s');
             } else {
                 $start_date = get_gmt_from_date($_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':00');
             }
             WC_Subscriptions_Manager::create_pending_subscription_for_order($order, $product_id, array('start_date' => $start_date));
             // Add the subscription meta for this item to the order
             $functions_and_meta = array('get_period' => '_order_subscription_periods', 'get_interval' => '_order_subscription_intervals', 'get_length' => '_order_subscription_lengths');
             foreach ($functions_and_meta as $function_name => $meta_key) {
                 $subscription_meta = self::get_meta($order, $meta_key, array());
                 $subscription_meta[$product_id] = WC_Subscriptions_Product::$function_name($product_id);
                 update_post_meta($order->id, $meta_key, $subscription_meta);
             }
             // This works because meta is added when the item is added via Ajax
             self::process_shop_order_item_meta($post_id, $post);
             // If the order's existing status is something other than pending and the order status is not being changed, manually set the subscription's status (otherwise, it will be handled when WC transitions the order's status)
             if ($order->status == $_POST['order_status'] && 'pending' != $order->status) {
                 switch ($order->status) {
                     case 'completed':
                     case 'processing':
                         WC_Subscriptions_Manager::activate_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'cancelled':
                         WC_Subscriptions_Manager::cancel_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'failed':
                         WC_Subscriptions_Manager::failed_subscription_signup($order->customer_user, $subscription_key);
                         break;
                 }
             }
         }
     }
     // Determine whether we need to update any subscription dates for existing subscriptions (before the item meta is updated)
     if (!empty($product_ids)) {
         $start_date = $_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . date(':s', strtotime($order->order_date));
         // Order's customer or start date changed for an existing order
         if ($customer_has_changed || !empty($order->order_date) && $order->order_date != $start_date) {
             self::$requires_update['expiration_date'] = array_values($product_ids);
             self::$requires_update['trial_expiration'] = array_values($product_ids);
             self::$requires_update['next_billing_date'] = array_values($product_ids);
         } elseif (isset($_POST['meta_key'])) {
             $item_meta_keys = isset($_POST['meta_key']) ? $_POST['meta_key'] : array();
             $new_meta_values = isset($_POST['meta_value']) ? $_POST['meta_value'] : array();
             foreach ($item_meta_keys as $item_meta_id => $meta_key) {
                 $meta_data = self::get_item_meta_data($item_meta_id);
                 $product_id = woocommerce_get_order_item_meta($meta_data->order_item_id, '_product_id');
                 // Set flags to update payment dates if required
                 switch ($meta_key) {
                     case '_subscription_period':
                     case '_subscription_interval':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_start_date':
                     case '_subscription_trial_length':
                     case '_subscription_trial_period':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['trial_expiration'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_length':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_trial_expiry_date':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['trial_expiration'][] = $product_id;
                         }
                         break;
                     case '_subscription_expiry_date':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                         }
                         break;
                 }
             }
         }
     }
 }
示例#27
0
 /**
  * Get line tax - useful for gateways.
  *
  * @param mixed $item
  * @return float
  */
 public function get_line_tax($item)
 {
     return apply_filters('woocommerce_order_amount_line_tax', is_callable(array($item, 'get_total_tax')) ? wc_round_tax_total($item->get_total_tax()) : 0, $item, $this);
 }
示例#28
0
 /**
  * Get the refunded amount for a line item.
  *
  * @param  int $item_id ID of the item we're checking
  * @param  int $tax_id ID of the tax we're checking
  * @param  string $item_type type of the item we're checking, if not a line_item
  * @return double
  */
 public function get_tax_refunded_for_item($item_id, $tax_id, $item_type = 'line_item')
 {
     $total = 0;
     foreach ($this->get_refunds() as $refund) {
         foreach ($refund->get_items($item_type) as $refunded_item) {
             if (absint($refunded_item->get_meta('_refunded_item_id')) === $item_id) {
                 $total += $refunded_item->get_total_tax();
             }
         }
     }
     return wc_round_tax_total($total) * -1;
 }
示例#29
0
if (empty($legacy_order) && 'yes' == get_option('woocommerce_calc_taxes')) {
    $line_tax_data = isset($item['line_tax_data']) ? $item['line_tax_data'] : '';
    $tax_data = maybe_unserialize($line_tax_data);
    foreach ($order_taxes as $tax_item) {
        $tax_item_id = $tax_item['rate_id'];
        $tax_item_total = isset($tax_data['total'][$tax_item_id]) ? $tax_data['total'][$tax_item_id] : '';
        $tax_item_subtotal = isset($tax_data['subtotal'][$tax_item_id]) ? $tax_data['subtotal'][$tax_item_id] : '';
        ?>
					<td class="line_tax" width="1%">
						<div class="view">
							<?php 
        if ('' != $tax_item_total) {
            if (isset($tax_item_subtotal) && $tax_item_subtotal != $tax_item_total) {
                echo '<del>' . wc_price(wc_round_tax_total($tax_item_subtotal)) . '</del> ';
            }
            echo wc_price(wc_round_tax_total($tax_item_total));
        } else {
            echo '&ndash;';
        }
        if ($refunded = $order->get_tax_refunded_for_item($item_id, $tax_item_id)) {
            echo '<small class="refunded">-' . wc_price($refunded) . '</small>';
        }
        ?>
						</div>
						<div class="edit" style="display: none;">
							<div class="split-input">
								<?php 
        $item_total_tax = isset($tax_item_total) ? esc_attr(wc_format_localized_price($tax_item_total)) : '';
        ?>
								<input type="text" name="line_tax[<?php 
        echo absint($item_id);
 public function test_wc_round_tax_total()
 {
     // Issue suggests this should be 22.34
     // https://github.com/kilbot/WooCommerce-POS/issues/79
     $this->assertEquals(22.35, wc_round_tax_total(22.345));
 }