Your issue is that you need to be able to tell the rules that the special is current active.
I have had the same issue in my Dynamic Category Products Extension, in that I needed to allow date range attributes to consider the dates that the attribute is active on. To make it more complex, you would need to consider the date range set to be in range on the day the category (or in your case, the product) is viewed.
I thus came up with a new rule condition that is as such:
Explaining how I did that would really take a bit of time, and the code is quite heavily integrated into the extensions code (as I added many other rule types)
What I can give you, and which you would be able to apply to any collection, is the way I altered the collection to filter out any products that are currently on special, taking into consideration the date range.
$collection is the actual product collection, as loaded from the current category.
The block below is the code I use in the validation routine for product attributes, and some parts will be out of contect. Please ask if you need some bits/parts further explained.
Basically it ads in a filter to the product collection, that includes (or excludes) products that has active special price to form date ranges.
case 'date':
$todayDate = Mage::app()->getLocale()->date()->toString(Varien_Date::DATE_INTERNAL_FORMAT);
switch ($operator) {
case 'inrange':
//TO
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'null' => true
),
array(
'attribute' => $attrCode,
'from' => $todayDate,
//'to' => $todayDate,
'date' => true
)
)
);
// FROM
$attrCodeFrom = str_replace('to', 'from', $attrCode);
if (array_key_exists($attrCode, $this->_dropAtrribute)) {
$attrCodeFrom = $this->_dropAtrribute[$attrCode];
}
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCodeFrom,
'null' => true
),
array(
'attribute' => $attrCodeFrom,
//'from' => $todayDate,
'to' => $todayDate,
'date' => true
)
)
);
// skip where both dates are null.
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'notnull' => true
),
array(
'attribute' => $attrCodeFrom,
'notnull' => true
)
)
);
$collection->setFlag('applied_date_ranges_' . $attrCode, true);
break;
case 'ninrange': // inverted
//TO
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'null' => true
),
array(
'attribute' => $attrCode,
'to' => $todayDate,
//'to' => $todayDate,
'date' => true
)
)
);
// FROM
$attrCodeFrom = str_replace('to', 'from', $attrCode);
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCodeFrom,
'null' => true
),
array(
'attribute' => $attrCodeFrom,
//'from' => $todayDate,
'from' => $todayDate,
'date' => true
)
)
);
// skip where both dates are null.
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'notnull' => true
),
array(
'attribute' => $attrCodeFrom,
'notnull' => true
)
)
);
$collection->setFlag('applied_date_ranges_' . $attrCode, true);
break;
case 'xdaysago':
$days = ($value == 1) ? 'day' : 'days';
$startDate = date('Y-m-d', strtotime('-' . $value . ' ' . $days, strtotime($todayDate)));
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'gteq' => $startDate,
'date' => true
)
)
);
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'notnull' => true
),
)
);
break;
default:
// all other date attributes
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
$operator => $value,
'date' => true
)
)
);
$collection->addAttributeToFilter(
array(
array(
'attribute' => $attrCode,
'notnull' => true
),
)
);
break;
}
break;
Hope this is of use to you.
One day, when I have time, I'd like to extract that rule (and some others I created) and build a community module that extends core catalog rules. One day, when I have time!!