/** calculate totals for the items in the cart */ public static function calculate_totals() { // extracted cart totals so that the constructor can call it, rather than // this full method. Cart totals are needed for cart widget and themes. // Don't want to call shipping api's multiple times per page load self::calculate_cart_total(); // Cart Shipping if (self::needs_shipping()) { jigoshop_shipping::calculate_shipping(self::$tax); } else { jigoshop_shipping::reset_shipping(); } self::$shipping_total = jigoshop_shipping::get_total(); $shipping_method = jigoshop_shipping::get_chosen_method(); if (self::get_options()->get('jigoshop_calc_taxes') == 'yes') { self::$tax->calculate_shipping_tax(self::$shipping_total, $shipping_method); self::$shipping_tax_total = self::$tax->get_total_shipping_tax_amount(); } // Subtotal self::$subtotal_ex_tax = self::$cart_contents_total_ex_tax; self::$subtotal = self::$cart_contents_total; if (self::get_options()->get('jigoshop_calc_taxes') == 'yes' && !self::$tax->get_total_shipping_tax_amount()) { foreach (self::get_applied_tax_classes() as $tax_class) { if (!self::is_not_compounded_tax($tax_class)) { //tax compounded $discount = self::get_options()->get('jigoshop_tax_after_coupon') == 'yes' ? self::$discount_total : 0; self::$tax->update_tax_amount($tax_class, (self::$subtotal_ex_tax - $discount + self::$tax->get_non_compounded_tax_amount() + self::$shipping_total) * 100); } } } self::$total = self::get_cart_subtotal(false) + self::get_cart_shipping_total(false); if (self::get_options()->get('jigoshop_calc_taxes') == 'yes' && self::get_options()->get('jigoshop_prices_include_tax') == 'no' && self::get_options()->get('jigoshop_tax_after_coupon') == 'no') { self::$total += self::$tax->get_non_compounded_tax_amount() + self::$tax->get_compound_tax_amount(); } // calculate any cart wide discounts from coupons $total_product_discounts = self::$discount_total; self::$discount_total = $total_cart_discounts = $temp = 0; if (self::get_options()->get('jigoshop_tax_after_coupon') == 'yes') { // we need products and shipping with tax out $total_cart_discounts = round(self::calculate_cart_discounts_total(self::$cart_contents_total_ex_tax + self::get_cart_shipping_total(false, true)), 2); if ($total_cart_discounts > 0) { $total_to_use = self::$cart_contents_total_ex_tax + self::$shipping_total; if ($total_cart_discounts > $total_to_use) { $total_cart_discounts = $total_to_use - $total_product_discounts; } $total_tax = self::$tax->get_non_compounded_tax_amount() + self::$tax->get_compound_tax_amount() - self::$tax->get_total_shipping_tax_amount(); if ($total_tax > 0) { foreach (self::get_applied_tax_classes() as $tax_class) { $rate = self::$tax->get_rate($tax_class); $tax = self::$tax->calc_tax(self::$price_per_tax_class_ex_tax[$tax_class], $rate, false); $discounts = 0.0; $total_tax_part = $tax / $total_tax; // Lower tax by coupon amounts foreach (jigoshop_cart::get_coupons() as $code) { $coupon = JS_Coupons::get_coupon($code); switch ($coupon['type']) { case 'fixed_cart': $discounts += self::$tax->calc_tax($coupon['amount'] * $total_tax_part, $rate, false); break; case 'percent': $discounts += self::$tax->calc_tax($coupon['amount'] * self::$price_per_tax_class_ex_tax[$tax_class] / ($total_tax_part * 100), $rate, false); $discounts += $coupon['amount'] * self::$tax->get_shipping_tax($tax_class) / 100; break; } } $tax -= $discounts; self::$tax->update_tax_amount($tax_class, $tax * 100, false, true); } } // check again in case tax calcs are disabled $total_discounts = $total_cart_discounts + $total_product_discounts; if ($total_discounts > $total_to_use) { $total_cart_discounts = $total_to_use - $total_product_discounts; } } foreach (self::get_applied_tax_classes() as $tax_class) { $temp += self::$tax->get_tax_amount($tax_class); } if (self::get_options()->get('jigoshop_prices_include_tax') == 'no') { self::$total += $temp; } else { self::$total = self::$cart_contents_total_ex_tax + self::$shipping_total + $temp; } } else { // Taxes are applied before coupons, 'jigoshop_tax_after_coupon' == 'no' if (self::get_options()->get('jigoshop_prices_include_tax') == 'no') { $total_cart_discounts = self::calculate_cart_discounts_total(self::$total); if ($total_cart_discounts > self::$total) { $total_cart_discounts = self::$total - $total_product_discounts; } } else { $total_cart_discounts = self::calculate_cart_discounts_total(self::$cart_contents_total_ex_tax + self::$shipping_total); if ($total_cart_discounts > 0) { // with an initial discount, recalc taxes and get a proper discount foreach (self::get_applied_tax_classes() as $tax_class) { $rate = self::$tax->get_rate($tax_class); $tax = self::$tax->calc_tax(self::$cart_contents_total_ex_tax, $rate, false); self::$tax->update_tax_amount($tax_class, $tax * 100, false, true); $temp += self::$tax->get_tax_amount($tax_class); } $total_to_use = self::$cart_contents_total_ex_tax + self::$shipping_total + $temp; $total_cart_discounts = self::calculate_cart_discounts_total($total_to_use); if ($total_cart_discounts > $total_to_use) { $total_cart_discounts = $total_to_use - $total_product_discounts; } } } } // set the final discount self::$discount_total = $total_cart_discounts + $total_product_discounts; // adjust the grand total after all discounts self::$total -= self::$discount_total; if (self::$total < 0) { self::$total = 0; } // with everything calculated, check that coupons depending on cart totals are still valid // if they are not, remove them and recursively re-calculate everything all over again. $recalc = false; if (!empty(self::$applied_coupons)) { foreach (self::$applied_coupons as $key => $code) { if (!self::is_valid_coupon($code)) { unset(self::$applied_coupons[$key]); jigoshop_session::instance()->coupons = self::$applied_coupons; $recalc = true; } } } if ($recalc) { self::calculate_totals(); } }