After a little code following and a few failed attempts, I found this to be a solution to the "central" issue described, though still need to identify a solution to the "difference" in price display/change of an attributes applied price... Ie. when looking in the attributes controller and seeing two prices in the Total | Disc column... It appears that when that is so, that the product page doesn't show the proper information to relate back to the actual total that will be seen once the product is added to the cart/displayed in checkout... But that's still somewhat of a separate issue.
So the "fix" is/was to duplicate an action that is in the includes/classes/shopping_cart.php file within the function cart(). Just prior to iterating each of the product a constant is defined:
Code:
if (!defined('ATTRIBUTES_PRICE_FACTOR_FROM_SPECIAL')) define('ATTRIBUTES_PRICE_FACTOR_FROM_SPECIAL', 1);
This causes the calculations on the shopping cart page to come out correctly as this affects the results of the includes/functions/functions_prices.php file's function zen_get_attributes_price_factor which in turn affects the function zen_get_attributes_price_final in the same file and also the shopping_cart class in multiple locations...
Well, one place in which that function is called is within the shopping_cart class' function attributes_price... Okay, no big deal right? Except, in the order class when generating the order price values, this class function is called to assign the final_price for each product... Thus... In order for the same "calculation" to be performed in the order class as is/was done in the shopping_cart class, a similar assignment of the constant is needed... Now.. The question becomes, should it be entered only in the shopping_cart class (three times: once in the cart function, once in the attributes_price function), should an instance be added to the order class just before the assignment of the total price so that it is defined for the attributes_price calculation as the order class uses the shopping_cart class to generate the values, or should it be applied site wide???
I chose to add it to the attributes_price calculation seeing as other functions call this class/function to perform calculations on the product and therefore it seems to make sense to apply it only there... (Yes in initial testing I did make it a global constant to see what/if anything would change in site operation.) The function is not used on the admin side, and the following store side files use this function in a default install:
includes/classes/shopping_cart.php
includes/classes/order.php
includes/modules/payment/sagepay_zc/SagepayBasket.php (Appears that the below correction will ensure proper pricing there for this setup.)
Now, using a setup similar to what has been described of a product having attributes with a price factor applied I've gone through a normal purchase without any further deductions, a sale (with a few variations of how to apply the sale), a special, combination of the two and while I did see a little oddity in calculating a sale where the new price was identified and the above setup established, it didn't seem directly related to the change (could include/exclude the constant and the result was effectively the same at the product level and responded as expected at the checkout area), but instead either my understanding or the setup... But that seems to also be a different issue.
So anyways, modifying the includes/classes/shopping_cart.php code to include the below highlighted item seemed to "fix" the issue of attributes + price factor + special price coming out to be the incorrect total at checkout.
Code:
function attributes_price($products_id) {
global $db, $currencies;
$total_attributes_price = 0;
$qty = $this->contents[$products_id]['qty'];
if (isset($this->contents[$products_id]['attributes'])) {
if (!defined('ATTRIBUTES_PRICE_FACTOR_FROM_SPECIAL')) define('ATTRIBUTES_PRICE_FACTOR_FROM_SPECIAL', 1); // mc12345678 Added to apply the attribute's price factor and price factor offset against the provided special price if a special is present otherwise against the provided price when returning the value from the function zen_get_attributes_price_factor found in includes/functions/functions_prices.php
reset($this->contents[$products_id]['attributes']);
while (list($option, $value) = each($this->contents[$products_id]['attributes'])) {
$attributes_price = 0;
Perhaps an improved solution would be to include some "flag" on each product such that the use of the specials price for attributes could be applied or not with the input to the function zen_get_attributes_price_factor would have the $price modified for that product such that
Code:
if (defined('ATTRIBUTES_PRICE_FACTOR_FROM_SPECIAL') && ATTRIBUTES_PRICE_FACTOR_FROM_SPECIAL == 1) {
if ($product[$i]['attribute_special_flag']) {
// do nothing but provide the $normal and $special values
} else {
$special = $normal;
}
} else {
if ($product[$i]['attribute_special_flag']) {
$normal = $special;
} else {
// do nothing but provide the $normal and $special values
}
}
zen_get_attributes_price_factor($normal, $special, $attributes_price_factor, $attributes_price_factor_offset);
That way, the individual product could be targeted, of course an alternative is to add a parameter to the function which when provided would allow lookup of that factor "on the spot" rather than having to modify other code to swap/consider the possibility... Whatever, just some thoughts. :)
Bookmarks