/** calculate totals for the items in the cart */ public static function calculate_totals() { $_tax = &new jigoshop_tax(); self::$total = 0; self::$cart_contents_total = 0; self::$cart_contents_total_ex_tax = 0; self::$cart_contents_weight = 0; self::$cart_contents_count = 0; self::$cart_contents_tax = 0; self::$tax_total = 0; self::$shipping_tax_total = 0; self::$subtotal = 0; self::$subtotal_ex_tax = 0; self::$discount_total = 0; self::$shipping_total = 0; self::$cart_dl_count = 0; if (sizeof(self::$cart_contents)>0) : foreach (self::$cart_contents as $item_id => $values) : $_product = $values['data']; if ($_product->exists() && $values['quantity']>0) : self::$cart_contents_count = self::$cart_contents_count + $values['quantity']; // If product is downloadable don't apply to product if( $_product->product_type == 'downloadable' ) { self::$cart_dl_count = self::$cart_dl_count + $values['quantity']; } self::$cart_contents_weight = self::$cart_contents_weight + ($_product->get_weight() * $values['quantity']); $total_item_price = $_product->get_price() * $values['quantity'] * 100; // Into pounds if ( get_option('jigoshop_calc_taxes')=='yes') : if ( $_product->is_taxable() ) : $rate = $_tax->get_rate( $_product->data['tax_class'] ); if (get_option('jigoshop_prices_include_tax')=='yes') : $tax_amount = $_tax->calc_tax( $total_item_price, $rate, true ); else : $tax_amount = $_tax->calc_tax( $total_item_price, $rate, false ); endif; if (get_option('jigoshop_prices_include_tax')=='yes' && jigoshop_customer::is_customer_outside_base() && defined('JIGOSHOP_CHECKOUT') && JIGOSHOP_CHECKOUT ) : /** * Our prices include tax so we need to take the base tax rate into consideration of our shop's country * * Lets get the base rate first */ $base_rate = $_tax->get_shop_base_rate( $_product->data['tax_class'] ); // Calc tax for base country $base_tax_amount = round($_tax->calc_tax( $total_item_price, $base_rate, true )); // Now calc tax for user county (which now excludes tax) $tax_amount = round($_tax->calc_tax( ($total_item_price-$base_tax_amount), $rate, false )); // Finally, update $total_item_price to reflect tax amounts $total_item_price = ($total_item_price - $base_tax_amount + $tax_amount); endif; endif; endif; $total_item_price = $total_item_price / 100; // Back to pounds $tax_amount = ( isset($tax_amount) ? $tax_amount : 0 ) / 100; // Back to pounds self::$cart_contents_tax = self::$cart_contents_tax + $tax_amount; self::$cart_contents_total = self::$cart_contents_total + $total_item_price; self::$cart_contents_total_ex_tax = self::$cart_contents_total_ex_tax + ($_product->get_price_excluding_tax() * $values['quantity']); // Product Discounts if (self::$applied_coupons) foreach (self::$applied_coupons as $code) : $coupon = jigoshop_coupons::get_coupon($code); if ($coupon['type']=='fixed_product' && in_array($item_id, $coupon['products'])) : self::$discount_total = self::$discount_total + ( $coupon['amount'] * $values['quantity'] ); endif; endforeach; endif; endforeach; endif; // Cart Shipping if (self::needs_shipping()) jigoshop_shipping::calculate_shipping(); self::$shipping_total = jigoshop_shipping::$shipping_total; self::$shipping_tax_total = jigoshop_shipping::$shipping_tax; self::$tax_total = self::$cart_contents_tax; // Subtotal self::$subtotal_ex_tax = self::$cart_contents_total_ex_tax; self::$subtotal = self::$cart_contents_total; // Cart Discounts if (self::$applied_coupons) foreach (self::$applied_coupons as $code) : $coupon = jigoshop_coupons::get_coupon($code); if (jigoshop_coupons::is_valid($code)) : if ($coupon['type']=='fixed_cart') : self::$discount_total = self::$discount_total + $coupon['amount']; elseif ($coupon['type']=='percent') : self::$discount_total = self::$discount_total + ( self::$subtotal / 100 ) * $coupon['amount']; endif; endif; endforeach; // Total if (get_option('jigoshop_prices_include_tax')=='yes') : self::$total = self::$subtotal + self::$shipping_tax_total - self::$discount_total + jigoshop_shipping::$shipping_total; else : self::$total = self::$subtotal + self::$tax_total + self::$shipping_tax_total - self::$discount_total + jigoshop_shipping::$shipping_total; endif; if (self::$total < 0) self::$total = 0; }
/** 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(); } }