You are here

function get_discounts_for_order in Ubercart Discounts (Alternative) 6.2

Returns discounts for order. Note: $order->uc_discounts_codes must be set

Parameters

$order Order to get discounts for:

$errors Reference to array to add error messages to:

$messages Reference to array to add success messages to:

Return value

array of discount objects

9 calls to get_discounts_for_order()
get_codeless_discounts_for_product_and_quantity in uc_discounts/uc_discounts.module
Returns all codeless discounts for product when specified quantity is purchased.
uc_checkout_pane_discounts in uc_discounts/uc_discounts.module
Discounts checkout pane callback
uc_discounts_apply in uc_discounts/uc_discounts.module
Applies the discounts to an order by creating the necessary line items.
uc_discounts_cart_pane_output in uc_discounts/uc_discounts.module
Adds the discounts to the cart page as line items via javascript
uc_discounts_condition_discount_applied in uc_discounts/uc_discounts.ca.inc
Determines if a discounts has been applied

... See full list

File

uc_discounts/uc_discounts.module, line 1155

Code

function get_discounts_for_order($order, &$errors = NULL, &$warnings = NULL, &$messages = NULL) {

  // Product NIDS in cart => subtotal of individual item
  $order_product_id_subtotal_map = array();

  // Product NIDS in cart => quantity of individual item
  $order_product_id_quantity_map = array();

  // Product NIDS in cart
  $order_product_ids = array();

  // Product NIDS in cart=> bool
  $order_product_ids_set = array();

  // Product objects in cart
  $order_product_id_product_array_map = array();
  $order_subtotal = 0;

  //Create IN string of product node IDs in order
  if (is_array($order->products) && !empty($order->products)) {
    foreach ($order->products as $product) {
      $nid = $product->nid;
      $order_product_ids_set[$nid] = TRUE;
      if (is_array($product->data) && !empty($product->data['kit_id'])) {
        $kit_id = $product->data['kit_id'];
        $order_product_ids_set[$kit_id] = TRUE;
        $kits[$kit_id]['product_qty'] += $product->qty;
      }
      uc_discounts_add_to_existing_map_number_value($order_product_id_subtotal_map, $nid, $product->price * $product->qty);
      uc_discounts_add_to_existing_map_number_value($order_product_id_quantity_map, $nid, $product->qty);
      $a = $order_product_id_product_array_map[$nid];
      if (!is_array($a)) {
        $a = array();
      }
      $a[] = $product;
      $order_product_id_product_array_map[$nid] = $a;
      $order_subtotal += $product->price * $product->qty;
    }
    if (is_array($kits) && !empty($kits)) {
      foreach ($kits as $kit_id => $value) {
        $kit_node = node_load($kit_id);
        foreach ($kit_node->products as $product_in_kit) {
          $pik_nid = $product_in_kit->nid;
          foreach ($order->products as $key => $product) {
            if ($product->nid == $pik_nid && $product->data['kit_id'] == $kit_id) {
              $kits[$kit_id]['kit_qty'] = $product->qty / $product_in_kit->qty;
              break;
            }
          }
        }
        uc_discounts_add_to_existing_map_number_value($order_product_id_quantity_map, $kit_id, $kits[$kit_id]['kit_qty']);
      }
    }
  }

  // Populate product NID array with NIDs from the order
  $order_product_ids = array_keys($order_product_ids_set);
  $temp_product_ids = $order_product_ids;
  $temp_product_ids[] = ALL_PRODUCTS;
  $product_ids_clause = sprintf("d.filter_type<>%d OR dp.product_id IN(%s)", FILTER_TYPE_PRODUCTS, join(",", $temp_product_ids));

  //Create IN string of term TIDs in order
  $temp_term_ids = array();
  $temp_term_ids[] = ALL_TERMS;
  if (is_array($order->products) && !empty($order->products)) {

    //Get terms for order's products
    $result = db_query("SELECT DISTINCT tid FROM {term_node} WHERE nid IN(%s)", join(",", $order_product_ids));
    while ($row = db_fetch_array($result)) {
      $temp_term_ids[] = $row["tid"];
      $order_term_ids[] = $row["tid"];
    }
  }
  $term_ids_clause = sprintf("d.filter_type<>%d OR dt.term_id IN(%s)", FILTER_TYPE_TERMS, join(",", $temp_term_ids));

  //Create IN string of SKUs in order
  $temp_skus = array();
  $temp_skus[] = "'" . db_escape_string(ALL_SKUS) . "'";
  if (is_array($order->products) && !empty($order->products)) {

    //Get SKUs for order's products
    $result = db_query("SELECT DISTINCT model FROM {uc_products} WHERE nid IN(%s)", join(",", $order_product_ids));
    while ($row = db_fetch_array($result)) {
      $temp_skus[] = "'" . db_escape_string($row["model"]) . "'";
    }
  }
  $skus_clause = sprintf("d.filter_type<>%d OR ds.sku IN(%s)", FILTER_TYPE_SKUS, join(",", $temp_skus));

  //Create IN string of classes in order
  $temp_classes = array();
  $temp_classes[] = "'" . db_escape_string(ALL_CLASSES) . "'";
  if (is_array($order->products) && !empty($order->products)) {

    //Get classes for order's products
    $result = db_query("SELECT DISTINCT type FROM {node} WHERE nid IN(%s)", join(",", $order_product_ids));
    while ($row = db_fetch_array($result)) {
      $temp_classes[] = "'" . db_escape_string($row["type"]) . "'";
    }
  }
  $classes_clause = sprintf("d.filter_type<>%d OR dcl.class IN(%s)", FILTER_TYPE_CLASS, join(",", $temp_classes));

  //Create IN string of authors in order
  $temp_authors = array();
  $temp_authors[] = "'" . db_escape_string(ALL_AUTHORS) . "'";
  if (is_array($order->products) && !empty($order->products)) {

    //Get authors for order's products
    $result = db_query("SELECT DISTINCT uid FROM {node} WHERE nid IN(%s)", join(",", $order_product_ids));
    while ($row = db_fetch_array($result)) {
      $temp_authors[] = "'" . db_escape_string($row["uid"]) . "'";
    }
  }
  $authors_clause = sprintf("d.filter_type<>%d OR dau.author_id IN(%s)", FILTER_TYPE_AUTHORS, join(",", $temp_authors));

  //Create codes clause
  $escaped_codes_string = NULL;
  if (!empty($order->uc_discounts_codes)) {

    //Create IN string of product node IDs in order
    $escaped_codes = array();
    foreach ($order->uc_discounts_codes as $code) {
      $escaped_codes[] = "'" . db_escape_string($code) . "'";
    }
    $escaped_codes_string = join(",", $escaped_codes);
    $codes_clause = sprintf(" OR d.discount_id IN( SELECT discount_id FROM {uc_discounts_codes} WHERE code IN(%s) )", $escaped_codes_string);
  }
  else {
    $codes_clause = "";
  }

  //Create roles clause
  $auth_rid = $order->uid != 0 ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
  $roles_clause = sprintf(" OR d.discount_id IN(SELECT dr.discount_id FROM {uc_discounts_roles} dr LEFT JOIN {users_roles} ur ON (dr.role_id=ur.rid AND ur.uid=%d) WHERE ur.uid IS NOT NULL OR dr.role_id=%d OR dr.role_id=%d)", $order->uid, ALL_ROLES, $auth_rid);
  $grouping = DISCOUNT_FILTER_GROUPING_APPLICATION;

  //Add warnings for expired discounts with codes (if necessary)
  if (!empty($order->uc_discounts_codes)) {
    $query = sprintf("SELECT DISTINCT d.*, dc.code code FROM {uc_discounts} d\n      LEFT JOIN {uc_discounts_products} dp ON d.discount_id=dp.discount_id AND dp.grouping = {$grouping}\n      LEFT JOIN {uc_discounts_terms} dt ON d.discount_id=dt.discount_id AND dt.grouping = {$grouping}\n      LEFT JOIN {uc_discounts_skus} ds ON d.discount_id=ds.discount_id AND ds.grouping = {$grouping}\n      LEFT JOIN {uc_discounts_classes} dcl ON d.discount_id=dcl.discount_id AND dcl.grouping = {$grouping}\n      LEFT JOIN {uc_discounts_authors} dau ON d.discount_id=dau.discount_id AND dau.grouping = {$grouping}\n      LEFT JOIN {uc_discounts_roles} dr ON d.discount_id=dr.discount_id\n      LEFT JOIN {uc_discounts_codes} dc ON d.discount_id=dc.discount_id\n      WHERE dc.code IN(%s)\n      AND (d.has_role_filter=0%s)\n      AND (%s)\n      AND (%s)\n      AND (%s)\n      AND (%s)\n      AND (%s)\n      AND (d.has_expiration<>0 AND d.expiration<=%d)\n      AND (d.is_active=%d)\n      ORDER BY weight", $escaped_codes_string, $roles_clause, $product_ids_clause, $term_ids_clause, $skus_clause, $classes_clause, $authors_clause, time(), IS_ACTIVE);
    $result = db_query($query);
    while ($discount = db_fetch_object($result)) {
      $warnings[] = t('The discount for code "@code" has expired.', array(
        "@code" => $discount->code,
      ));
    }
  }
  $query = sprintf("SELECT DISTINCT d.* FROM {uc_discounts} d\n    LEFT JOIN {uc_discounts_products} dp ON d.discount_id=dp.discount_id AND dp.grouping = {$grouping}\n    LEFT JOIN {uc_discounts_terms} dt ON d.discount_id=dt.discount_id AND dt.grouping = {$grouping}\n    LEFT JOIN {uc_discounts_skus} ds ON d.discount_id=ds.discount_id AND ds.grouping = {$grouping}\n    LEFT JOIN {uc_discounts_classes} dcl ON d.discount_id=dcl.discount_id AND dcl.grouping = {$grouping}\n    LEFT JOIN {uc_discounts_authors} dau ON d.discount_id=dau.discount_id AND dau.grouping = {$grouping}\n    WHERE (d.requires_code=0%s)\n    AND (d.has_role_filter=0%s)\n    AND (%s)\n    AND (%s)\n    AND (%s)\n    AND (%s)\n    AND (%s)\n    AND (d.has_activation=0 OR d.activates_on<%d)\n    AND (d.has_expiration=0 OR d.expiration>%d)\n    AND (d.is_active=%d)\n    ORDER BY weight", $codes_clause, $roles_clause, $product_ids_clause, $term_ids_clause, $skus_clause, $classes_clause, $authors_clause, time(), time(), IS_ACTIVE);
  $result = db_query($query);
  $total_discount_amount = 0;
  $discounts = array();

  // Appears to check if order qualifies for each discount then applies discount.  Functionality should be separated, no?
  while ($discount = db_fetch_object($result)) {
    foreach (module_implements('uc_discount') as $module) {
      $function = $module . '_uc_discount';
      $function('load', $discount, $order);
    }

    // In case the hook modified the discount
    if (!$discount->is_active) {
      continue;
    }

    //Get code for discount (if one exists)
    $discount->code = NULL;
    if (!empty($escaped_codes_string)) {
      $query = sprintf("SELECT code FROM {uc_discounts_codes} WHERE code IN(%s) AND discount_id=%d", $escaped_codes_string, $discount->discount_id);
      $row = db_fetch_array(db_query($query));
      if (!empty($row)) {
        $discount->code = $row["code"];
      }
    }

    //The query handled valid codes and expiration, this block must:

    //  check max uses (if applicable)
    //  check if discount is being combined and can be combined
    //  check if order qualifies (type, requires_single_product_to_qualify, required_products, can_be_combined_with_other_discounts)
    //  determine number of times to apply discount

    //If this discount has a max uses amount, check max uses
    if ($discount->max_uses > 0) {
      $row = db_fetch_array(db_query("SELECT COUNT(*) as uses_count FROM {uc_discounts_uses} WHERE discount_id=%d", $discount->discount_id));
      if ($row["uses_count"] >= $discount->max_uses) {

        //If this is a coded discount, add error message
        if (!is_null($warnings) && !is_null($discount->code)) {
          $warnings[] = t('The discount for code "@code" has reached its maximum number of uses.', array(
            "@code" => $discount->code,
          ));
        }
        continue;
      }
      $discount->uses_count = $row["uses_count"];
    }

    //If this discount has a max uses per user amount, check max uses per user
    if ($discount->max_uses_per_user > 0) {
      $row = db_fetch_array(db_query("SELECT COUNT(*) as user_uses_count FROM {uc_discounts_uses} WHERE discount_id=%d AND user_id=%d", $discount->discount_id, $order->uid));
      if ($row["user_uses_count"] >= $discount->max_uses_per_user) {

        //If this is a coded discount, add warning message
        if (!is_null($warnings) && !is_null($discount->code)) {
          $warnings[] = t('The discount for code "@code" has reached its maximum number of uses.', array(
            "@code" => $discount->code,
          ));
        }
        continue;
      }
      $discount->user_uses_count = $row["user_uses_count"];
    }

    //If code exists and this discount has a max uses per code amount, check max uses per code
    if (!is_null($discount->code) && $discount->max_uses_per_code > 0) {
      $row = db_fetch_array(db_query("SELECT COUNT(*) as code_uses_count FROM {uc_discounts_uses} WHERE discount_id=%d AND code='%s'", $discount->discount_id, $discount->code));
      if ($row["code_uses_count"] >= $discount->max_uses_per_code) {

        //Add warning message
        if (!is_null($warnings)) {
          $warnings[] = t('The discount code "@code" has reached its max number of uses.', array(
            "@code" => $discount->code,
          ));
        }
        continue;
      }
      $discount->code_uses_count = $row["code_uses_count"];
    }

    //If there are applied discounts, check if discount is being combined and can be combined
    if (count($discounts) > 0) {
      if (!$discount->can_be_combined_with_other_discounts) {

        //If this is a coded discount, add error message
        if (!is_null($warnings) && !is_null($discount->code)) {
          $warnings[] = t('The discount for code "@code" cannot be combined with other discounts.', array(
            "@code" => $discount->code,
          ));
        }
        continue;
      }

      // Check if the first discount can't be combined
      if (!$discounts[0]->can_be_combined_with_other_discounts) {

        //If first discount was a coded discount, add error message (only print warning if both

        //discounts have codes)
        if (!is_null($warnings) && !empty($discounts[0]->code) && !is_null($discount->code)) {
          $warnings[] = t('The discount for code "@code" cannot be combined with other discounts.', array(
            "@code" => $discounts[0]->code,
          ));
        }
        continue;
      }
    }

    //Check if order qualifies for this discount (check type, requires_single_product_to_qualify, required_products)

    //Get product IDs for determining discount application
    $discount_product_ids = get_product_ids_for_discount_object($discount);
    if (in_array(ALL_PRODUCTS, $discount_product_ids)) {
      $discount_product_ids = $order_product_ids;
    }

    // Get product IDs for determining discount qualification
    $required_product_ids = get_product_ids_for_discount_object($discount, DISCOUNT_FILTER_GROUPING_QUALIFICATION);
    $required_ids_in_order = array_intersect($required_product_ids, $order_product_ids);
    if (!empty($discount->code) && !empty($required_product_ids) && empty($required_ids_in_order)) {
      $warnings[] = t('The discount for code "@code" requires a product that is not in your cart.', array(
        '@code' => $discount->code,
      ));
      continue;
    }
    if ($discount->use_only_discounted_products_to_qualify) {
      $qualification_product_ids = $discount_product_ids;
    }
    elseif (!empty($required_product_ids)) {
      $qualification_product_ids = $required_product_ids;
    }
    else {
      $qualification_product_ids = $order_product_ids;
    }

    //Determine total qualifying amount of order (store in order_qualifying_amount)
    $order_qualifying_amount = 0;
    switch ($discount->qualifying_type) {
      case QUALIFYING_TYPE_MINIMUM_PRICE:

        //Determine the total subtotal of discount's products
        foreach ($qualification_product_ids as $product_id) {
          if (isset($order_product_id_subtotal_map[$product_id])) {
            if ($discount->requires_single_product_to_qualify) {
              if ($order_product_id_subtotal_map[$product_id] >= $order->qualifying_amount) {

                //In this case, $order_qualifying amount should be the sum of

                //prices of products that both qualify and meet the minimum

                //qualification amount based on their individual price.
                $order_qualifying_amount += $order_product_id_subtotal_map[$product_id];
              }
            }
            else {
              $order_qualifying_amount += $order_product_id_subtotal_map[$product_id];
            }
          }
        }

        //Subtract already discounted amount
        $order_qualifying_amount -= $total_discount_amount;
        break;
      case QUALIFYING_TYPE_MINIMUM_QUANTITY:

        //Determine the total quantity of discount's products
        foreach ($qualification_product_ids as $product_id) {
          if (isset($order_product_id_quantity_map[$product_id])) {
            if ($discount->requires_single_product_to_qualify) {
              if ($order_product_id_quantity_map[$product_id] >= $discount->qualifying_amount) {

                //In this case, $order_qualifying amount should be the sum of products that both qualify and meet the minimum qualification amount based on their quantity.
                $order_qualifying_amount += $order_product_id_quantity_map[$product_id];
              }
            }
            else {
              $order_qualifying_amount += $order_product_id_quantity_map[$product_id];
            }
          }
        }
        break;
    }

    //If order does not qualify for this discount
    if ($order_qualifying_amount < $discount->qualifying_amount) {

      //If this is a coded discount, add warning message
      if (!is_null($warnings) && !is_null($discount->code)) {
        switch ($discount->qualifying_type) {
          case QUALIFYING_TYPE_MINIMUM_PRICE:
            $qualifying_amount = uc_currency_format($discount->qualifying_amount);
            $warnings[] = t('The discount for code "@code" requires a minimum amount of @qualifying_amount to qualify.', array(
              "@code" => $discount->code,
              "@qualifying_amount" => $qualifying_amount,
            ));
            break;
          case QUALIFYING_TYPE_MINIMUM_QUANTITY:
            $warnings[] = t('The discount for code "@code" requires a minimum quantity of @qualifying_amount to qualify.', array(
              "@code" => $discount->code,
              "@qualifying_amount" => $discount->qualifying_amount,
            ));
            break;
        }
      }
      continue;
    }

    //If this discount has a maximum qualifying amount and the order exceeds it
    if ($discount->has_qualifying_amount_max && $order_qualifying_amount > $discount->qualifying_amount_max) {

      //If this is a coded discount, add error message
      if (!is_null($warnings) && !is_null($discount->code)) {
        $qualifying_amount_max = uc_currency_format($discount->qualifying_amount_max);
        switch ($discount->qualifying_type) {
          case QUALIFYING_TYPE_MINIMUM_PRICE:
            $warnings[] = t('The discount for code "@code" cannot exceed the price of @qualifying_amount_max to qualify.', array(
              "@code" => $discount->code,
              "@qualifying_amount_max" => $qualifying_amount_max,
            ));
            break;
          case QUALIFYING_TYPE_MINIMUM_QUANTITY:
            $warnings[] = t('The discount for code "@code" cannot exceed the quantity of @qualifying_amount_max to qualify.', array(
              "@code" => $discount->code,
              "@qualifying_amount_max" => $discount->qualifying_amount_max,
            ));
            break;
        }
      }
      continue;
    }

    //Get product IDs in order that are in discount
    $order_and_discount_product_ids = array_intersect($discount_product_ids, $order_product_ids);

    //Create array of product objects in cart to which this discount gets applied.
    $order_and_discount_products = array();
    foreach ($order_and_discount_product_ids as $product_id) {
      if (array_key_exists($product_id, $order_product_id_product_array_map)) {
        $order_and_discount_products = array_merge($order_and_discount_products, $order_product_id_product_array_map[$product_id]);
      }
    }

    // Amount of products to which discounts get applied
    $discount_products_amount = 0;

    // Quantity of products to which discounts get applied
    $discount_products_qty = 0;
    foreach ($order_and_discount_products as $product) {
      $discount_products_qty += $product->qty;
      $discount_products_amount += $product->qty * $product->price;
    }

    // Determine number of times to apply discount, by default once for every qualifying product
    $discount->times_applied = $discount_products_qty;

    // See if it should be limited based on number of required products in the cart
    if ($discount->limit_max_times_applied && !empty($required_product_ids)) {
      $times = 0;
      foreach ($required_product_ids as $id) {
        if (isset($order_product_id_quantity_map[$id])) {
          $times += $order_product_id_quantity_map[$id];
        }
      }
      $discount->times_applied = min($discount->times_applied, $times);
    }

    // See if we need to limit the number of applications with a hard cap
    if ($discount->max_times_applied != 0) {
      $discount->times_applied = min($discount->times_applied, $discount->max_times_applied);
    }
    switch ($discount->discount_type) {
      case DISCOUNT_TYPE_FREE_ITEMS:

        //The variable discount_amount is the monitary amount of discount
        $discount_amount = 0;

        //The variable free_items_remaining is the [max] number of free items for the order
        $free_items_remaining = $discount->discount_amount * $discount->times_applied;

        //Loop until all free items have been applied or there are no more products to

        //discount (discount cheapest first)
        while ($free_items_remaining > 0) {

          //Determine cheapest remaining qualifying item
          $cheapest_product = NULL;
          foreach ($order_and_discount_products as $product) {

            //If this product has been fully discounted, continue
            if ($product->uc_discounts_is_fully_discounted) {
              continue;
            }

            //If no current cheapest product exists, use this product
            if (is_null($cheapest_product)) {
              $cheapest_product = $product;
            }
            else {

              //If this product is cheaper than the current cheapest product,

              //use this product instead
              if ($product->price < $cheapest_product->price) {
                $cheapest_product = $product;
              }
            }
          }

          //If no cheapest product could be found, there are no more products to

          //discount, break
          if (is_null($cheapest_product)) {
            break;
          }

          //Discount up to the lesser of cheapest product quantity and free_items_remaining
          $discount_count = min($cheapest_product->qty, $free_items_remaining);

          //Add current discount amount to running total
          $discount_amount += $discount_count * $cheapest_product->price;

          //Mark item fully discounted
          $cheapest_product->uc_discounts_is_fully_discounted = TRUE;
          $free_items_remaining -= $discount_count;
        }
        $discount->amount = $discount_amount;
        break;
      case DISCOUNT_TYPE_PERCENTAGE_OFF_PER_QUALIFYING_ITEM:
        $discount->amount = $discount_products_amount / $discount_products_qty * $discount->discount_amount * $discount->times_applied;
        break;
      case DISCOUNT_TYPE_PERCENTAGE_OFF:

        // This is so complicated because we need to ensure only qualifying
        // products get discounted and no product is discounted more than 100%
        // Always apply once since it applies to the whole order
        $discount->times_applied = 1;

        //If this discount uses all products and previous discount is:

        //  same weight as this discount
        //  percentage off
        //  products of discounts must match

        //discount using same subtotal as last discount
        if (count($discounts) > 0) {
          $last_discount = $discounts[count($discounts) - 1];
          if ($last_discount->weight == $discount->weight && $last_discount->discount_type == DISCOUNT_TYPE_PERCENTAGE_OFF) {

            //Last discount's and this discount's products must match exactly
            $are_equal = TRUE;
            $last_discount_product_ids = get_product_ids_for_discount_object($last_discount);
            $this_discount_product_ids = get_product_ids_for_discount_object($discount);

            //If both contain "all products" they are equal
            if (in_array(ALL_PRODUCTS, $last_discount_product_ids) && in_array(ALL_PRODUCTS, $this_discount_product_ids)) {
              $are_equal = TRUE;
            }
            else {
              foreach ($this_discount_product_ids as $product_id) {
                if (!in_array($product_id, $last_discount_product_ids)) {
                  $are_equal = FALSE;
                  break;
                }
              }
              if ($are_equal) {
                foreach ($last_discount_product_ids as $product_id) {
                  if (!in_array($product_id, $this_discount_product_ids)) {
                    $are_equal = FALSE;
                    break;
                  }
                }
              }
            }
            if ($are_equal) {

              //($last_discount->amount / $last_discount->discount_amount) == last discount's subtotal
              $local_order_subtotal = $last_discount->amount / $last_discount->discount_amount;
              $discount->amount = $local_order_subtotal * $discount->discount_amount;
              break;
            }
          }
        }

        //Start patch from lutegrass:

        //This fixes the problem where a percent discount does not apply to all products

        //(but doesn't fix the problem where the products being discounted have already been discounted

        //in full, or the case where the cart consists only of the products included in this discount)

        // Get qualifying products -- ignore "all products" selection
        $discount_product_ids = get_product_ids_for_discount_object($discount, DISCOUNT_FILTER_GROUPING_APPLICATION, TRUE);

        // Do we have any products
        if (count($discount_product_ids) > 0) {
          $discounted_products_amount = 0;
          foreach ($order_and_discount_products as $product) {
            $discounted_products_amount += $product->price * $product->qty;
          }
          $discount->amount = $discounted_products_amount * $discount->discount_amount;

          // Discount the subtotal so far
        }
        else {
          $discount->amount = max($order_subtotal - $total_discount_amount, 0) * $discount->discount_amount;
        }

        //End patch from lutegrass
        break;
      case DISCOUNT_TYPE_FIXED_AMOUNT_OFF:

        // Always apply once since it applies to the whole order
        $discount->times_applied = 1;
        $discount->amount = $discount->discount_amount;
        break;
      case DISCOUNT_TYPE_FIXED_AMOUNT_OFF_PER_QUALIFYING_ITEM:
        $discount->amount = $discount->discount_amount * $discount->times_applied;
        break;
    }
    if (!is_null($messages)) {
      $options = array(
        "@short_description" => $discount->short_description,
        "@code" => $discount->code,
        "@times_applied" => $discount->times_applied,
        "@discount_amount" => uc_currency_format($discount->amount),
        "@time_string" => $time_string,
      );
      if (!is_null($discount->code)) {
        if (empty($discount->amount)) {
          $messages[] = t("The discount, '@short_description', with code '@code' was applied.", $options);
        }
        elseif ($discount->times_applied == 1) {
          $messages[] = t("The discount, '@short_description', with code '@code' was applied for a discount of @discount_amount.", $options);
        }
        else {
          $messages[] = t("The discount, '@short_description', with code '@code' was applied @times_applied times for a discount of @discount_amount.", $options);
        }
      }
      else {
        if (empty($discount->amount)) {
          $messages[] = t("The discount, '@short_description' was applied.", $options);
        }
        elseif ($discount->times_applied == 1) {
          $messages[] = t("The discount, '@short_description', was applied for a discount of @discount_amount.", $options);
        }
        else {
          $messages[] = t("The discount, '@short_description', was applied @times_applied times for a discount of @discount_amount.", $options);
        }
      }
    }

    //Round the discount to two places
    $discount->amount = round($discount->amount, 2);

    //Add this discount's amount to running total
    $total_discount_amount += $discount->amount;

    //Add this discount to list of discounts applied to order
    $discounts[] = $discount;
  }

  // If no discount array was filled in, means that the discount was not found in the database
  if (count($discounts) == 0 && !empty($order->uc_discounts_codes)) {
    $warnings[] = t('Coupon does not exist or is not valid.');
  }

  // end of db fetch while loop
  return $discounts;
}