/** * Aggregates product pricing information * * @author Jonathan Davis * @since 1.1 * * @param array $options shopp() tag option list * @return void **/ public function pricing(&$records, &$price, $restat = false) { if (isset($this->products) && !empty($this->products)) { if (!isset($this->products[$price->product])) { return false; } if (!isset($this->_last_product)) { $this->_last_product = false; } if ($this->_last_product != false && $this->_last_product != $price->product && isset($this->products[$this->_last_product])) { $this->products[$this->_last_product]->sumup(); } if ($this->_last_product != $price->product) { $this->products[$price->product]->resum(); } $target =& $this->products[$price->product]; $this->_last_product = $price->product; } else { $target =& $this; } // Skip calulating variant pricing when variants are not enabled for the product if (!(isset($target->variants) && Shopp::str_true($target->variants)) && 'variation' == $price->context) { return; } $target->prices[] = $price; // Force to floats $price->price = (double) $price->price; $price->saleprice = (double) $price->saleprice; $price->shipfee = (double) $price->shipfee; $price->promoprice = (double) Shopp::str_true($price->sale) ? $price->saleprice : $price->price; // Build secondary lookup table using the price id as the key $target->priceid[$price->id] = $price; // Set promoprice before data aggregation if (Shopp::str_true($price->sale)) { $price->promoprice = $price->saleprice; } // Do not count disabled price lines or addon price lines in aggregate summary stats if ('N/A' == $price->type || 'addon' == $price->context) { return; } // Simple product or variant product is on sale if (Shopp::str_true($price->sale)) { $target->sale = $price->sale; } // Build third lookup table using the combined optionkey $target->pricekey[$price->optionkey] = $price; if (Shopp::str_true($price->inventory)) { $target->stock += $price->stock; $target->inventory = $price->inventory; $target->lowstock($price->stock, $price->stocked); } $freeshipping = false; if (!Shopp::str_true($price->shipping) && 'Shipped' == $price->type) { $freeshipping = true; } // Calculate catalog discounts if not already calculated if (!empty($price->discounts)) { $discount = ShoppPromo::pricing($price->promoprice, $price->discounts); if ($discount->freeship) { $freeshipping = true; } $price->promoprice = $discount->pricetag; } $price->_sale = $price->sale; // Keep a copy of the price record "sale" setting {@see issue #2797} if ($price->promoprice < $price->price) { $target->sale = $price->sale = 'on'; } // Grab price and saleprice ranges (minimum - maximum) if (!$price->price) { $price->price = 0; } // Variation range index/properties $varranges = array('price' => 'price', 'saleprice' => 'promoprice'); if (Shopp::str_true($price->inventory)) { $varranges['stock'] = 'stock'; } foreach ($varranges as $name => $prop) { if (!isset($price->{$prop})) { continue; } if (!isset($target->min[$name]) || $target->min[$name] == 0) { $target->min[$name] = $price->{$prop}; } else { $target->min[$name] = min($target->min[$name], $price->{$prop}); } if ($target->min[$name] == $price->{$prop}) { $target->min[$name . '_tax'] = $price->tax == "on"; } if (!isset($target->max[$name])) { $target->max[$name] = $price->{$prop}; } else { $target->max[$name] = max($target->max[$name], $price->{$prop}); } if ($target->max[$name] == $price->{$prop}) { $target->max[$name . '_tax'] = $price->tax == "on"; } } // Determine savings ranges if (Shopp::str_true($target->sale)) { if (!isset($target->min['saved']) || $target->min['saved'] === false) { $target->min['saved'] = $price->price; $target->min['savings'] = 100; $target->max['saved'] = $target->max['savings'] = 0; } $target->min['saved'] = min($target->min['saved'], $price->price - $price->promoprice); $target->max['saved'] = max($target->max['saved'], $price->price - $price->promoprice); // Find lowest savings percentage $delta = $price->price - $price->promoprice; if ($price->price == 0) { // no savings possible $target->min['savings'] = 0; } else { if ($delta <= 0) { // total savings $target->max['savings'] = 100; } else { $savings = $delta / $price->price * 100; $target->min['savings'] = min($target->min['savings'], $savings); $target->max['savings'] = max($target->max['savings'], $savings); } } } if (shopp_setting_enabled('inventory') && Shopp::str_true($target->inventory)) { $target->outofstock = $target->stock <= 0; } if ($freeshipping) { $target->freeship = 'on'; } }
/** * Calculates promotional discounts applied to the price record * * @author Jonathan Davis * @since 1.1 * * @return boolean True if a discount applies **/ public function discounts() { if (empty($this->discounts)) { return false; } $pricetag = Shopp::str_true($this->sale) ? $this->saleprice : $this->price; $discount = ShoppPromo::pricing($pricetag, $this->discounts); $this->promoprice = $discount->pricetag; if ($discount->freeship) { $this->freeship = true; } return true; }