コード例 #1
0
 /**
  * Function to apply Gift Certificate's credit to cart
  */
 public function apply_smart_coupon_to_cart()
 {
     $this->global_wc()->cart->smart_coupon_credit_used = array();
     $cart_contains_subscription = false;
     if (class_exists('WC_Subscriptions_Cart') && WC_Subscriptions_Cart::cart_contains_subscription()) {
         $cart_contains_subscription = true;
     }
     if ($cart_contains_subscription) {
         $calculation_type = WC_Subscriptions_Cart::get_calculation_type();
         if ($calculation_type == 'recurring_total') {
             return;
         }
     }
     if ($this->global_wc()->cart->applied_coupons) {
         foreach ($this->global_wc()->cart->applied_coupons as $code) {
             $smart_coupon = new WC_Coupon($code);
             if ($smart_coupon->is_valid() && $smart_coupon->discount_type == 'smart_coupon') {
                 $order_total = $this->global_wc()->cart->cart_contents_total + $this->global_wc()->cart->tax_total + $this->global_wc()->cart->shipping_tax_total + $this->global_wc()->cart->shipping_total;
                 if ($this->global_wc()->cart->discount_total != 0 && $this->global_wc()->cart->discount_total + $smart_coupon->amount > $order_total) {
                     $smart_coupon->amount = $order_total - $this->global_wc()->cart->discount_total;
                 } elseif ($smart_coupon->amount > $order_total) {
                     $smart_coupon->amount = $order_total;
                 }
                 $this->global_wc()->cart->discount_total = $this->global_wc()->cart->discount_total + $smart_coupon->amount;
                 if ($cart_contains_subscription) {
                     WC_Subscriptions_Cart::increase_coupon_discount_amount($code, $smart_coupon->amount);
                 }
                 $this->global_wc()->cart->smart_coupon_credit_used[$code] = $smart_coupon->amount;
                 //Code for displaying the price label for the store credit coupons
                 if (empty($this->global_wc()->cart->coupon_discount_amounts)) {
                     $this->global_wc()->cart->coupon_discount_amounts = array();
                 }
                 $this->global_wc()->cart->coupon_discount_amounts[$code] = $smart_coupon->amount;
             }
         }
     }
 }
 /**
  * Removes the "set_subscription_prices_for_calculation" filter from the WC Product's woocommerce_get_price hook once
  *
  * @since 1.5.10
  */
 public static function set_prorated_price_for_calculation($price, $product)
 {
     if (WC_Subscriptions_Product::is_subscription($product) && self::is_product_prorated($product) && in_array(WC_Subscriptions_Cart::get_calculation_type(), array('combined_total', 'none'))) {
         $next_payment_date = self::calculate_first_payment_date($product, 'timestamp');
         if (self::is_today($next_payment_date)) {
             return $price;
         }
         switch ($product->subscription_period) {
             case 'week':
                 $days_in_cycle = 7 * $product->subscription_period_interval;
                 break;
             case 'month':
                 $days_in_cycle = date('t') * $product->subscription_period_interval;
                 break;
             case 'year':
                 $days_in_cycle = (365 + date('L')) * $product->subscription_period_interval;
                 break;
         }
         $days_until_next_payment = ceil(($next_payment_date - gmdate('U')) / (60 * 60 * 24));
         if ('combined_total' == WC_Subscriptions_Cart::get_calculation_type()) {
             $sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee($product);
             if ($sign_up_fee > 0 && 0 == WC_Subscriptions_Product::get_trial_length($product)) {
                 $price = $sign_up_fee + $days_until_next_payment * (($price - $sign_up_fee) / $days_in_cycle);
             }
         } elseif ('none' == WC_Subscriptions_Cart::get_calculation_type()) {
             $price = $days_until_next_payment * ($price / $days_in_cycle);
         }
     }
     return $price;
 }
 /**
  * Sets which coupons should be applied for this calculation.
  *
  * This function is hooked to "woocommerce_before_calculate_totals" so that WC will calculate a subscription
  * product's total based on the total of it's price per period and sign up fee (if any).
  *
  * @since 1.3.5
  */
 public static function remove_coupons($cart)
 {
     global $woocommerce;
     $calculation_type = WC_Subscriptions_Cart::get_calculation_type();
     // Only hook when totals are being calculated completely (on cart & checkout pages)
     if ('none' == $calculation_type || !WC_Subscriptions_Cart::cart_contains_subscription() || !is_checkout() && !is_cart() && !defined('WOOCOMMERCE_CHECKOUT') && !defined('WOOCOMMERCE_CART')) {
         return;
     }
     $applied_coupons = $cart->get_applied_coupons();
     // If we're calculating a sign-up fee or recurring fee only amount, remove irrelevant coupons
     if (!empty($applied_coupons)) {
         // Keep track of which coupons, if any, need to be reapplied immediately
         $coupons_to_reapply = array();
         if (in_array($calculation_type, array('combined_total', 'sign_up_fee_total', 'recurring_total'))) {
             foreach ($applied_coupons as $coupon_code) {
                 $coupon = new WC_Coupon($coupon_code);
                 if (in_array($coupon->type, array('recurring_fee', 'recurring_percent'))) {
                     // always apply coupons to their specific calculation case
                     if ('recurring_total' == $calculation_type) {
                         $coupons_to_reapply[] = $coupon_code;
                     } elseif ('combined_total' == $calculation_type && !WC_Subscriptions_Cart::cart_contains_free_trial()) {
                         // sometimes apply recurring coupons to initial total
                         $coupons_to_reapply[] = $coupon_code;
                     } else {
                         self::$removed_coupons[] = $coupon_code;
                     }
                 } elseif (in_array($calculation_type, array('combined_total', 'sign_up_fee_total', 'none')) && !in_array($coupon->type, array('recurring_fee', 'recurring_percent'))) {
                     // apply all coupons to the first payment
                     $coupons_to_reapply[] = $coupon_code;
                 } else {
                     self::$removed_coupons[] = $coupon_code;
                 }
             }
             // Now remove all coupons (WC only provides a function to remove all coupons)
             $cart->remove_coupons();
             // And re-apply those which relate to this calculation
             $woocommerce->cart->applied_coupons = $coupons_to_reapply;
         }
     }
 }
コード例 #4
0
 /**
  * Apply sign up fee or recurring fee discount
  *
  * @since 1.2
  */
 public static function apply_subscription_discount($original_price, $cart_item, $cart)
 {
     _deprecated_function(__METHOD__, '2.0.10', 'Have moved to filtering on "woocommerce_coupon_get_discount_amount" to return discount amount. See: ' . __CLASS__ . '::get_discount_amount()');
     $product_id = $cart_item['data']->is_type(array('subscription_variation')) ? $cart_item['data']->variation_id : $cart_item['data']->id;
     if (!WC_Subscriptions_Product::is_subscription($product_id)) {
         return $original_price;
     }
     $price = $calculation_price = $original_price;
     $calculation_type = WC_Subscriptions_Cart::get_calculation_type();
     if (!empty($cart->applied_coupons)) {
         foreach ($cart->applied_coupons as $code) {
             $coupon = new WC_Coupon($code);
             // Pre 2.5 is_valid_for_product() does not use wc_get_product_coupon_types()
             if (WC_Subscriptions::is_woocommerce_pre('2.5')) {
                 $is_valid_for_product = true;
             } else {
                 $is_valid_for_product = $coupon->is_valid_for_product(wc_get_product($product_id), $cart_item);
             }
             if ($coupon->apply_before_tax() && $coupon->is_valid() && $is_valid_for_product) {
                 $apply_recurring_coupon = $apply_recurring_percent_coupon = $apply_initial_coupon = $apply_initial_percent_coupon = false;
                 // Apply recurring fee discounts to recurring total calculations
                 if ('recurring_total' == $calculation_type) {
                     $apply_recurring_coupon = 'recurring_fee' == $coupon->type ? true : false;
                     $apply_recurring_percent_coupon = 'recurring_percent' == $coupon->type ? true : false;
                 }
                 if ('none' == $calculation_type) {
                     // If all items have a free trial we don't need to apply recurring coupons to the initial total
                     if (!WC_Subscriptions_Cart::all_cart_items_have_free_trial()) {
                         if ('recurring_fee' == $coupon->type) {
                             $apply_initial_coupon = true;
                         }
                         if ('recurring_percent' == $coupon->type) {
                             $apply_initial_percent_coupon = true;
                         }
                     }
                     // Apply sign-up discounts to initial total
                     if (!empty($cart_item['data']->subscription_sign_up_fee)) {
                         if ('sign_up_fee' == $coupon->type) {
                             $apply_initial_coupon = true;
                         }
                         if ('sign_up_fee_percent' == $coupon->type) {
                             $apply_initial_percent_coupon = true;
                         }
                         $calculation_price = $cart_item['data']->subscription_sign_up_fee;
                     }
                 }
                 if ($apply_recurring_coupon || $apply_initial_coupon) {
                     $discount_amount = $calculation_price < $coupon->amount ? $calculation_price : $coupon->amount;
                     // Recurring coupons only apply when there is no free trial (carts can have a mix of free trial and non free trial items)
                     if ($apply_initial_coupon && 'recurring_fee' == $coupon->type && !empty($cart_item['data']->subscription_trial_length)) {
                         $discount_amount = 0;
                     }
                     $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity'];
                     $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']);
                     $price = $price - $discount_amount;
                 } elseif ($apply_recurring_percent_coupon) {
                     $discount_amount = round($calculation_price / 100 * $coupon->amount, WC()->cart->dp);
                     $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity'];
                     $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']);
                     $price = $price - $discount_amount;
                 } elseif ($apply_initial_percent_coupon) {
                     // Recurring coupons only apply when there is no free trial (carts can have a mix of free trial and non free trial items)
                     if ('recurring_percent' == $coupon->type && empty($cart_item['data']->subscription_trial_length)) {
                         $amount_to_discount = $cart_item['data']->subscription_price;
                     } else {
                         $amount_to_discount = 0;
                     }
                     // Sign up fee coupons only apply to sign up fees
                     if ('sign_up_fee_percent' == $coupon->type) {
                         $amount_to_discount = $cart_item['data']->subscription_sign_up_fee;
                     }
                     $discount_amount = round($amount_to_discount / 100 * $coupon->amount, WC()->cart->dp);
                     $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity'];
                     $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']);
                     $price = $price - $discount_amount;
                 }
             }
         }
         if ($price < 0) {
             $price = 0;
         }
     }
     return $price;
 }
コード例 #5
0
 /**
  * Removes the "set_subscription_prices_for_calculation" filter from the WC Product's woocommerce_get_price hook once
  *
  * @since 1.5.10
  */
 public static function set_prorated_price_for_calculation($price, $product)
 {
     if (WC_Subscriptions_Product::is_subscription($product) && self::is_product_prorated($product) && 'none' == WC_Subscriptions_Cart::get_calculation_type()) {
         $next_payment_date = self::calculate_first_payment_date($product, 'timestamp');
         if (self::is_today($next_payment_date)) {
             return $price;
         }
         switch ($product->subscription_period) {
             case 'week':
                 $days_in_cycle = 7 * $product->subscription_period_interval;
                 break;
             case 'month':
                 $days_in_cycle = date('t') * $product->subscription_period_interval;
                 break;
             case 'year':
                 $days_in_cycle = (365 + date('L')) * $product->subscription_period_interval;
                 break;
         }
         $days_until_next_payment = ceil(($next_payment_date - gmdate('U')) / (60 * 60 * 24));
         $sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee($product);
         if ($sign_up_fee > 0 && 0 == WC_Subscriptions_Product::get_trial_length($product)) {
             $price = $sign_up_fee + $days_until_next_payment * (($price - $sign_up_fee) / $days_in_cycle);
         } else {
             $price = $days_until_next_payment * ($price / $days_in_cycle);
         }
         // Now round the amount to the number of decimals displayed for prices to avoid rounding errors in the total calculations (we don't want to use WC_DISCOUNT_ROUNDING_PRECISION here because it can still lead to rounding errors). For full details, see: https://github.com/Prospress/woocommerce-subscriptions/pull/1134#issuecomment-178395062
         $price = round($price, wc_get_price_decimals());
     }
     return $price;
 }
 /**
  * Returns an array of order items in a TaxCloud friendly format
  *
  * array(
  *   [item_key] => array (
  *		[TIC] => TIC or empty string
  * 	   	[ItemID] => Product ID
  * 		[Index] => Item index (can be left blank for our purposes; re-assigned in generate_lookup_data)
  * 		[Type] => Item type (Values: cart, fee, shipping)
  * 		[Price] => The item price
  * 		[Qty] => The quantity of the item being purchased 
  *	)
  * )
  *
  * @since 4.2
  * @return (array) array of items (see above for structure)
  */
 private function get_items_array()
 {
     $items = $this->cart->cart_contents;
     $based_on = WC_WooTax::get_option('tax_based_on');
     $final_items = array();
     // Add cart items
     foreach ($items as $item_key => $item) {
         $product = $item['data'];
         // Get product TIC
         $tic_raw = get_post_meta($product->id, 'wootax_tic', true);
         $tic = $tic_raw == false ? '' : trim($tic_raw);
         // Get product ID, Qty, and Price
         $item_id = $item_key;
         $product_price = $item['line_total'] / $item['quantity'];
         if ($based_on == 'item-price' || !$based_on) {
             $qty = $item['quantity'];
             $price = $product_price;
         } else {
             $qty = 1;
             $price = $product_price * $item['quantity'];
         }
         // Add to final items array
         $final_items[$item_key] = array('Index' => NULL, 'ItemID' => $item_id, 'Price' => $price, 'Qty' => $qty, 'Type' => 'cart');
         // Only add TIC if it is set
         if (!empty($tic)) {
             $final_items[$item_key]['TIC'] = $tic;
         }
     }
     // Add fees
     $fees = $this->cart->get_fees();
     if (is_array($fees)) {
         foreach ($fees as $ind => $fee) {
             // Skip if not taxable (TODO: phase this out too?)
             if (isset($fee->taxable) && !$fee->taxable) {
                 continue;
             }
             // Get fee identifier (fee index since we are in checkout)
             $fee_id = $fee->id;
             // Get fee amount $fee->amount
             $amt = $fee->amount;
             // Add to final items array
             $final_items[$fee_id] = array('Index' => NULL, 'ItemID' => $fee_id, 'TIC' => WT_FEE_TIC, 'Qty' => 1, 'Price' => $amt, 'Type' => 'fee');
         }
     }
     // Add shipping costs
     $shipping_total = $this->cart->shipping_total;
     if ($this->is_subscription) {
         if (!WC_Subscriptions_Cart::charge_shipping_up_front() && (WC_Subscriptions_Cart::get_calculation_type() == 'sign_up_fee_total' || WC_Subscriptions_Cart::get_calculation_type() == 'free_trial_total')) {
             $shipping_total = 0;
         }
     }
     if ($shipping_total > 0) {
         // Add a shipping item to the final items array (we assume that only one shipping method is being used per order)
         $final_items[WT_SHIPPING_ITEM] = array('Index' => NULL, 'ItemID' => WT_SHIPPING_ITEM, 'TIC' => WT_SHIPPING_TIC, 'Qty' => 1, 'Price' => $shipping_total, 'Type' => 'shipping');
     }
     return $final_items;
 }