function uc_coupon_calculate_discounts in Ubercart Discount Coupons 6
Same name and namespace in other branches
- 7.3 uc_coupon.module \uc_coupon_calculate_discounts()
- 7.2 uc_coupon.module \uc_coupon_calculate_discounts()
Find items that a coupon will apply to and calculate the discounts.
Parameters
$coupon: The coupon object to be applied.
$order: The order to which it should be applied.
Return value
mixed An array of discounted items, each with a 'discount' field containing the total discount applied to that item; or, if there are no applicable discounts, a string indicating the reason why.
2 calls to uc_coupon_calculate_discounts()
- uc_coupon_tax_adjustment in ./
uc_coupon.module - Handle tax on coupons by calculating tax for individual discounted prices. This is currently only supported by the VAT module (uc_vat).
- uc_coupon_validate in ./
uc_coupon.module - Validate a coupon, and optionally calculate the order discount.
File
- ./
uc_coupon.module, line 606 - Provides discount coupons for Ubercart.
Code
function uc_coupon_calculate_discounts($coupon, $order) {
$context = array(
'revision' => 'altered',
'type' => 'cart_item',
'subject' => array(
'order' => $order,
),
);
$restricted = isset($coupon->data['products']) || isset($coupon->data['skus']) || isset($coupon->data['terms']) || isset($coupon->data['product_types']);
// Discover if any items match the restrictions, and which items the discount should be calculated against.
$matched = 0;
$matched_price = 0;
$total_qty = 0;
$total_price = 0;
$items = array();
foreach ($order->products as $item) {
if ($item->module == 'uc_coupon') {
continue;
}
$node = node_load($item->nid);
$context['subject']['cart_item'] = $item;
$context['subject']['node'] = $node;
$item->altered_price = uc_price($item->price, $context);
$qty = $item->qty;
if (!$restricted) {
// Coupons with no restrictions apply to all products.
$include = TRUE;
}
else {
// Other coupons only apply to matching products.
$include = FALSE;
$terms = isset($node->taxonomy) ? array_keys($node->taxonomy) : array();
if (isset($coupon->data['products']) && isset($item->data['kit_id'])) {
// Items that are part of product kits must be included or excluded all together, so we pre-empt other restrictions.
$include = (isset($coupon->data['negate_products']) xor in_array($item->data['kit_id'], $coupon->data['products']));
}
else {
if (isset($coupon->data['products']) && (isset($coupon->data['negate_products']) xor in_array($item->nid, $coupon->data['products']))) {
$include = TRUE;
}
else {
if (isset($coupon->data['products']) && isset($coupon->data['negate_products']) && in_array($item->nid, $coupon->data['products'])) {
// always exclude if in list of negated products
}
else {
if (isset($coupon->data['terms']) && (isset($coupon->data['negate_terms']) xor count(array_intersect($terms, $coupon->data['terms'])))) {
$include = TRUE;
}
else {
if (isset($coupon->data['terms']) && isset($coupon->data['negate_terms']) && count(array_intersect($terms, $coupon->data['terms']))) {
// always exclude if one of the terms is in the list of negated terms
}
else {
if (isset($coupon->data['skus']) && _uc_coupon_match_sku($item->model, $coupon->data['skus'])) {
$include = TRUE;
}
else {
if (isset($coupon->data['product_types']) && in_array($node->type, $coupon->data['product_types'])) {
$include = TRUE;
}
}
}
}
}
}
}
}
// A matching product was found.
if ($include) {
$matched += $qty;
$matched_price += $item->altered_price * $qty;
}
$total_qty += $qty;
$total_price += $item->altered_price * $qty;
// Coupons that apply to the order subtotal affect all products.
if ($include || $coupon->data['apply_to'] == 'subtotal') {
$items = array_pad($items, count($items) + $qty, $item);
}
}
// If no matches were found, there are no discounts to calculate.
if ($matched == 0) {
return t('You do not have any applicable products in your cart.');
}
// Ensure that the minimum order quantity restriction is met, if specified.
if (($coupon->data['minimum_qty_restrict'] ? $matched : $total_qty) < $coupon->data['minimum_qty']) {
return t('You do not have enough applicable products in your cart.');
}
if (($coupon->data['minimum_qty_restrict'] ? $matched_price : $total_price) < $coupon->minimum_order) {
return $coupon->data['minimum_qty_restrict'] ? t('You have not reached the minimum total of applicable products for this coupon.') : t('You have not reached the minimum order total for this coupon.');
}
// Ensure that all products match, if specified.
if (isset($coupon->data['require_match_all']) && $matched < $total_qty) {
return t('You have non-applicable products in your cart');
}
// Slice off applicable products if a limit was set.
switch ($coupon->data['apply_to']) {
case 'cheapest':
usort($items, '_uc_coupon_sort_products');
$items = array_slice($items, 0, $coupon->data['apply_count']);
break;
case 'expensive':
usort($items, '_uc_coupon_sort_products');
$items = array_slice($items, -$coupon->data['apply_count']);
break;
}
$total = 0;
foreach ($items as $item) {
$total += $item->altered_price;
}
foreach ($items as &$item) {
switch ($coupon->type) {
case 'price':
if ($coupon->data['apply_to'] == 'subtotal' || $coupon->data['apply_to'] == 'products_total') {
// Apply single discount proportionally across all qualifying items.
$item->discount = $total == 0 ? 0 : min($coupon->value * $item->price / $total, $item->price);
}
else {
// Apply discount to each product's untaxed price.
$item->discount = min($coupon->value * $item->price / $item->altered_price, $item->price);
}
break;
case 'percentage':
$item->discount = $item->price * $coupon->value / 100;
break;
case 'set_price':
$item->discount = max($item->price - $coupon->value * $item->price / $item->altered_price, 0);
break;
}
}
return $items;
}