Во-первых, я сделал бы интерфейс iPriceCalc, и набор классов, реализующих этот интерфейс, и все расчеты вынес бы в них. (Соответственно, в классе должен быть один метод, в который передается информация о товаре и, на всякий случай, залогиненном пользователе.) Плюс на всякий случай предусмотрел бы для каждого товара предусмотреть возможность указывать в базе, какой именно класс для расчета цены должен использоваться.
Редактор динамических скидок сделал бы так: таблица, в каждой ее строке несколько selectов. В первом из них выбираем, что именно проверяем (текущее число, текущий день недели, текущее время, цена продукта, категория и т.п.). Во втором — операция проверки (меньше, больше, равно, не равно). В третьем - значение с которым сравниваем.
В конце таблицы — размер скидки и ее тип (абсолютная в рублях или относительная в процентах).
Все это сохраняем в массив (с помощью сериализации в PHP или JSON) и передаем классу, осуществляющему расчет цены. Он проходит этот массив последовательно, берет каждую строку, подставляет вместо первого selectа реальное значение, смотрит, какую операцию нужно применить и сравнивает. Если все условия в наборе выполнились, скидка применяется и класс возвращает исправленную цену.
То есть получаем примерно такой:
class ConditionPriceCalculator implements iPriceCalc {
function calc($product,$user) {
$data = get_file_contents('файл с условиями');
$conditions = unserialize($data);
$result = true;
foreach ($conditions as $condition) {
// в поле comp_value лежит условное значение из первого selectа, для которого нужно посчитать реальное значение
if ($condition['comp_value']=='day') $value1==date('d');
elseif ($condition['comp_value']=='weekday') $value1=date('N');
// ... и так далее
$value=$condition['value']; // тут хранится, с чем сравнивать
if ($condition['op']=='eq') $cur_res = $value1==$value2;
if ($condition['op']=='ne') $cur_res = $value1!=$value2;
// и т.д.
if (!$cur_res) $result = false; // если условие не выполнилось, общий результат сбрасываем в false, еще можно добавить break;
}
if ($result) {
// если все условия из набора выполнились, рассчитываем новую цену:
}
}
}
В принципе, можно предусмотреть, чтобы таких наборов условий было несколько и применялся первый сработавший.
Единственное ограничение — это то, что нельзя в одном наборе условий объединять их по "ИЛИ", а не по "И".