/** * Returns aggregate discount amount applicable to order. * * @param array $order Order data array * @param bool $apply Whether discount-related information must be added to order parameters (where appropriate) * @return float Total discount value expressed in order currency */ public static function calculate(&$order, $apply = false) { $currency = isset($order['currency']) ? $order['currency'] : wa('shop')->getConfig()->getCurrency(false); $applicable_discounts = array(); $contact = self::getContact($order); // Discount by contact category applicable? if (self::isEnabled('category')) { $applicable_discounts[] = self::byCategory($order, $contact, $apply); } // Discount by coupon applicable? if (self::isEnabled('coupons')) { $applicable_discounts[] = self::byCoupons($order, $contact, $apply); } // Discount by order total applicable? if (self::isEnabled('order_total')) { $crm = new shopCurrencyModel(); $dbsm = new shopDiscountBySumModel(); // Order total in default currency $order_total = (double) $crm->convert($order['total'], $currency, wa('shop')->getConfig()->getCurrency()); $applicable_discounts[] = max(0.0, min(100.0, (double) $dbsm->getDiscount('order_total', $order_total))) * $order['total'] / 100.0; } // Discount by customer total spent applicable? if (self::isEnabled('customer_total')) { $applicable_discounts[] = self::byCustomerTotal($order, $contact, $apply); } /** * @event order_calculate_discount * @param array $params * @param array[string] $params['order'] order info array('total' => '', 'items' => array(...)) * @param array[string] $params['contact'] contact info * @param array[string] $params['apply'] calculate or apply discount * @return float discount */ $event_params = array('order' => &$order, 'contact' => $contact, 'apply' => $apply); $plugins_discounts = wa('shop')->event('order_calculate_discount', $event_params); foreach ($plugins_discounts as $plugin_discount) { $applicable_discounts[] = $plugin_discount; } // Select max discount or sum depending on global setting. $discount = 0.0; if ($applicable_discounts = array_filter($applicable_discounts, 'is_numeric')) { if (wa('shop')->getSetting('discounts_combine') == 'sum') { $discount = (double) array_sum($applicable_discounts); } else { $discount = (double) max($applicable_discounts); } } // Discount based on affiliate bonus? if (shopAffiliate::isEnabled()) { $discount = $discount + (double) shopAffiliate::discount($order, $contact, $apply, $discount); } return min(max(0, $discount), ifset($order['total'], 0)); }