/** * Returns the amount of points earned for the purchase, calculated by getting the points earned for each individual * product purchase multiplied by the quantity being ordered * * @since 1.0 */ private function get_points_earned_for_purchase($order) { $points_earned = 0; foreach ($order->get_items() as $item_key => $item) { $product = $order->get_product_from_item($item); if (!is_object($product)) { continue; } // If prices include tax, we include the tax in the points calculation if (get_option('woocommerce_prices_include_tax') == 'no') { // Get the un-discounted price paid and adjust our product price // Get item subtotal was buggy pre 2.0.19 if (version_compare(WOOCOMMERCE_VERSION, '2.0.19', '<')) { $item_price = $item['line_subtotal'] / $item['qty']; $item_price = number_format($item_price, 2, '.', ''); } else { $item_price = $order->get_item_subtotal($item, false, true); } } else { // Get the un-discounted price paid and adjust our product price // Get item subtotal was buggy pre 2.0.19 if (version_compare(WOOCOMMERCE_VERSION, '2.0.19', '<')) { $item_price = ($item['line_subtotal'] + $item['line_subtotal_tax']) / $item['qty']; $item_price = number_format($item_price, 2, '.', ''); } else { $item_price = $order->get_item_subtotal($item, true, true); } } $product->set_price($item_price); // Calc points earned $points_earned += WC_Points_Rewards_Product::get_points_earned_for_product_purchase($product, $item_price) * $item['qty']; } // reduce by any discounts. One minor drawback: if the discount includes a discount on tax and/or shipping // it will cost the customer points, but this is a better solution than granting full points for discounted orders $discount = $order->order_discount + $order->cart_discount; $points_earned -= min(WC_Points_Rewards_Manager::calculate_points($discount), $points_earned); // check if applied coupons have a points modifier and use it to adjust the points earned $coupons = $order->get_used_coupons(); if (!empty($coupons)) { $points_modifier = 0; // get the maximum points modifier if there are multiple coupons applied, each with their own modifier foreach ($coupons as $coupon_code) { $coupon = new WC_Coupon($coupon_code); if (!empty($coupon->coupon_custom_fields['_wc_points_modifier'][0]) && $coupon->coupon_custom_fields['_wc_points_modifier'][0] > $points_modifier) { $points_modifier = $coupon->coupon_custom_fields['_wc_points_modifier'][0]; } } if ($points_modifier > 0) { $points_earned = round($points_earned * ($points_modifier / 100)); } } return apply_filters('wc_points_rewards_points_earned_for_purchase', $points_earned, $order); }
/** * Points and Rewards single product message for per-product priced Bundles. * @param string $message * @param WC_Points_Rewards_Product $points_n_rewards * @return string */ public static function points_rewards_composite_message($message, $points_n_rewards) { global $product; if ($product->product_type == 'composite') { if (!$product->is_priced_per_product()) { return $message; } // Will calculate points based on min_composite_price, which is saved as _price meta $composite_points = WC_Points_Rewards_Product::get_points_earned_for_product_purchase($product); $message = $points_n_rewards->create_at_least_message_to_product_summary($composite_points); } return $message; }
/** * Return zero points for bundled cart items if container item has product level points. * * @param int $points * @param string $cart_item_key * @param array $cart_item_values * @return int */ function points_earned_for_bundled_cart_item($points, $cart_item_key, $cart_item_values) { if (isset($cart_item_values['bundled_by'])) { $cart_contents = WC()->cart->get_cart(); $bundle_cart_id = $cart_item_values['bundled_by']; $bundle = $cart_contents[$bundle_cart_id]['data']; // check if earned points are set at product-level $bundle_points = WC_Points_Rewards_Product::get_product_points($bundle); $per_product_priced_bundle = $bundle->is_priced_per_product(); $has_bundle_points = is_numeric($bundle_points) ? true : false; if ($has_bundle_points || $per_product_priced_bundle == false) { $points = 0; } else { $points = WC_Points_Rewards_Manager::calculate_points($cart_item_values['data']->get_price()); } } return $points; }
/** * Returns the maximum possible discount available given the total amount of points the customer has * * @since 1.0 */ public static function get_discount_for_redeeming_points($applying = false) { global $woocommerce; // get the value of the user's point balance $available_user_discount = WC_Points_Rewards_Manager::get_users_points_value(get_current_user_id()); // no discount if ($available_user_discount <= 0) { return 0; } if ($applying && 'yes' === get_option('wc_points_rewards_partial_redemption_enabled') && !empty($woocommerce->session->wc_points_rewards_discount_amount)) { $requested_user_discount = WC_Points_Rewards_Manager::calculate_points_value($woocommerce->session->wc_points_rewards_discount_amount); if ($requested_user_discount > 0 && $requested_user_discount < $available_user_discount) { $available_user_discount = $requested_user_discount; } } $discount_applied = 0; if (!did_action('woocommerce_before_calculate_totals')) { $woocommerce->cart->calculate_totals(); } // calculate the discount to be applied by iterating through each item in the cart and calculating the individual // maximum discount available foreach ($woocommerce->cart->get_cart() as $item_key => $item) { $discount = 0; $max_discount = WC_Points_Rewards_Product::get_maximum_points_discount_for_product($item['data']); if (is_numeric($max_discount)) { // adjust the max discount by the quantity being ordered $max_discount *= $item['quantity']; // if the discount available is greater than the max discount, apply the max discount $discount = $available_user_discount <= $max_discount ? $available_user_discount : $max_discount; // Max should be product price. As this will be applied before tax, it will respect other coupons. } else { // Use the line price - this is the max we can apply here if (method_exists($item['data'], 'get_price_including_tax')) { $max_discount = $item['data']->get_price_including_tax($item['quantity']); } else { $max_discount = $item['data']->get_price() * $item['quantity']; } // if the discount available is greater than the max discount, apply the max discount $discount = $available_user_discount <= $max_discount ? $available_user_discount : $max_discount; } // add the discount to the amount to be applied $discount_applied += $discount; // reduce the remaining discount available to be applied $available_user_discount -= $discount; } // if the available discount is greater than the order total, make the discount equal to the order total less any other discounts if (get_option('woocommerce_prices_include_tax') == 'no') { $discount_applied = max(0, min($discount_applied, $woocommerce->cart->subtotal_ex_tax - $woocommerce->cart->discount_total)); } else { $discount_applied = max(0, min($discount_applied, $woocommerce->cart->subtotal - $woocommerce->cart->discount_total)); } // limit the discount available by the global maximum discount if set $max_discount = get_option('wc_points_rewards_cart_max_discount'); if ($max_discount && $max_discount < $discount_applied) { $discount_applied = $max_discount; } return $discount_applied; }