This commit is contained in:
2026-03-16 00:25:33 +01:00
parent 6db4bbef56
commit 5cefdc42d4
4 changed files with 316 additions and 12 deletions

View File

@@ -148,14 +148,95 @@ class OmnibusEuFree extends Module
return (!empty($sqlResult)) ? $sqlResult[0] : array();
}
protected function hasDifferentHistoricalPrice($id_product, $id_product_attribute, $currency, $currentPrice)
{
$info_version = Configuration::get('OMNIBUSEUFREE_INFORMATION_VERSION', null, null, null, 2);
$numberOfDays = (int) Configuration::get('OMNIBUSEUFREE_DAYS', null, null, null, 30);
$date = new DateTime();
$date->modify('-' . $numberOfDays . ' days');
$cutOffDate = $date->format('Y-m-d');
$sql = new DbQuery();
$sql->select('id_omnibuseufree');
$sql->from('omnibus_eu_free');
$sql->where('id_product = ' . (int) $id_product);
$sql->where('id_product_attribute = ' . (int) $id_product_attribute);
$sql->where('id_currency = ' . (int) $currency);
$sql->where('date_add >= "' . pSQL($cutOffDate . ' 00:00:00') . '"');
$sql->where('ABS(price - ' . (float) $currentPrice . ') > 0.000001');
if ($info_version == 2) {
$sql->where('is_last = 0');
}
$sql->limit(1);
return (bool) Db::getInstance()->getValue($sql);
}
protected function formatDisplayPrice($price, $currency, $precisionOverride = null)
{
if ($precisionOverride !== null) {
$priceDisplayPrecision = (int) $precisionOverride;
} else {
$priceDisplayPrecision = (int) Configuration::get('PS_PRICE_DISPLAY_PRECISION', null, null, null, _PS_PRICE_DISPLAY_PRECISION_);
}
$roundedPrice = Tools::ps_round((float) $price, $priceDisplayPrecision);
return PrestashopCompatibility::formatPrice(_PS_VERSION_, $roundedPrice, $currency);
}
public function hookDisplayOmnibusEuFree($params)
{
$currency = $this->context->currency;
$lastMinimalPrice = $this->getLastMinimalPrice($params['product']['id_product'], $params['product']['id_product_attribute'], $currency->id);
$debugEnabled = (bool) Tools::getValue('omnibuseufree_debug');
$idProduct = isset($params['product']['id_product']) ? (int) $params['product']['id_product'] : 0;
$idProductAttribute = isset($params['product']['id_product_attribute']) ? (int) $params['product']['id_product_attribute'] : 0;
$lastMinimalPrice = $this->getLastMinimalPrice($idProduct, $idProductAttribute, $currency->id);
$regularPrice = isset($params['product']['regular_price']) ? $params['product']['regular_price'] : null;
$displayPrecisionOverride = null;
$forcedFallbackNoPreDiscountHistory = false;
if (isset($params['product']['price_amount']) && is_numeric($params['product']['price_amount'])) {
$priceAmount = (float) $params['product']['price_amount'];
if (abs($priceAmount - round($priceAmount)) < 0.000001) {
$displayPrecisionOverride = 0;
}
}
$fallbackPrice = null;
if (is_string($regularPrice) && $regularPrice !== '') {
// Prefer the already prepared regular (non-discounted) price from product presenter.
$fallbackPrice = $regularPrice;
} elseif ($idProduct > 0) {
// Compute regular (without reduction) price if presenter did not provide it.
$useTax = Product::getTaxCalculationMethod((int) $this->context->customer->id) != PS_TAX_EXC;
$regularRaw = Product::getPriceStatic($idProduct, $useTax, $idProductAttribute, 6, null, false, false);
$fallbackPrice = $this->formatDisplayPrice((float) $regularRaw, $currency, $displayPrecisionOverride);
} elseif (isset($params['product']['price_amount']) && is_numeric($params['product']['price_amount'])) {
// Last resort if product id is missing in hook params.
$fallbackPrice = $this->formatDisplayPrice((float) $params['product']['price_amount'], $currency, $displayPrecisionOverride);
} elseif (isset($params['product']['price']) && is_numeric($params['product']['price'])) {
$fallbackPrice = $this->formatDisplayPrice((float) $params['product']['price'], $currency, $displayPrecisionOverride);
} elseif (isset($params['product']['price']) && is_string($params['product']['price']) && $params['product']['price'] !== '') {
$fallbackPrice = $params['product']['price'];
}
if (!empty($lastMinimalPrice)) {
$minimalPrice = PrestashopCompatibility::formatPrice(_PS_VERSION_, $lastMinimalPrice['price'], $currency);
if (
!empty($params['product']['has_discount']) &&
isset($params['product']['price_amount']) &&
is_numeric($params['product']['price_amount']) &&
!$this->hasDifferentHistoricalPrice($idProduct, $idProductAttribute, $currency->id, (float) $params['product']['price_amount'])
) {
$lastMinimalPrice = array();
$forcedFallbackNoPreDiscountHistory = true;
}
}
if (!empty($lastMinimalPrice)) {
$minimalPrice = $this->formatDisplayPrice($lastMinimalPrice['price'], $currency, $displayPrecisionOverride);
}
else {
$minimalPrice = null;
@@ -166,8 +247,26 @@ class OmnibusEuFree extends Module
'OmnibuseufreeProductPriceMin' => $minimalPrice,
'OmnibuseufreeProductPriceCurrent' => $params['product']['price'],
'OmnibuseufreeProductPriceRegular' => $regularPrice,
'OmnibuseufreeProductPriceFallback' => $fallbackPrice,
'OmnibuseufreeProductDiscount' => (bool) $params['product']['has_discount'],
'OmnibuseufreeNumberOfDays' => (int) Configuration::get('OMNIBUSEUFREE_DAYS', null, null, null, 30),
'OmnibuseufreeDebugEnabled' => $debugEnabled,
'OmnibuseufreeDebugData' => [
'marker' => 'omnibuseufree-debug-2026-03-16',
'product_id' => $idProduct,
'product_attribute_id' => $idProductAttribute,
'currency_id' => isset($currency->id) ? (int) $currency->id : null,
'currency_iso' => isset($currency->iso_code) ? (string) $currency->iso_code : '',
'price_display_precision' => (int) Configuration::get('PS_PRICE_DISPLAY_PRECISION', null, null, null, _PS_PRICE_DISPLAY_PRECISION_),
'display_precision_override' => $displayPrecisionOverride === null ? 'null' : (string) $displayPrecisionOverride,
'param_price' => isset($params['product']['price']) ? (string) $params['product']['price'] : null,
'param_price_amount' => isset($params['product']['price_amount']) ? (string) $params['product']['price_amount'] : null,
'param_regular_price' => isset($params['product']['regular_price']) ? (string) $params['product']['regular_price'] : null,
'computed_fallback' => (string) $fallbackPrice,
'computed_minimal' => (string) $minimalPrice,
'has_discount' => !empty($params['product']['has_discount']) ? '1' : '0',
'forced_fallback_no_pre_discount_history' => $forcedFallbackNoPreDiscountHistory ? '1' : '0',
],
]);
return $this->display(__FILE__, '/views/templates/hook/presta_studio_omnibus_price.tpl');
@@ -194,7 +293,7 @@ class OmnibusEuFree extends Module
foreach ($rowValue as $key => $value) {
if (isset($OmnibusData[$rowId]['price']) && $key == 'id_currency') {
$currency = Currency::getCurrencyInstance((int) $value);
$OmnibusData[$rowId]['price_locale'] = PrestashopCompatibility::formatPrice(_PS_VERSION_, $OmnibusData[$rowId]['price'], $currency);
$OmnibusData[$rowId]['price_locale'] = $this->formatDisplayPrice($OmnibusData[$rowId]['price'], $currency);
$OmnibusData[$rowId]['currency_iso_code'] = $currency->iso_code;
}
elseif ($key == 'id_product_attribute') {

View File

@@ -21,7 +21,7 @@
{l s='Lowest price in %d days before discount: ' sprintf=[$OmnibuseufreeNumberOfDays] mod='omnibuseufree'}<span class="presta-studio-price-history-price">{$OmnibuseufreeProductPriceMin}</span>
{else}
{* when history is empty *}
{l s='Lowest price in %d days: ' sprintf=[$OmnibuseufreeNumberOfDays] mod='omnibuseufree'}<span class="presta-studio-price-history-price">{$OmnibuseufreeProductPriceRegular|default:$OmnibuseufreeProductPriceCurrent}</span>
{l s='Lowest price in %d days: ' sprintf=[$OmnibuseufreeNumberOfDays] mod='omnibuseufree'}<span class="presta-studio-price-history-price">{$OmnibuseufreeProductPriceFallback|default:$OmnibuseufreeProductPriceCurrent}</span>
{/if}
{else}
{l s='Lowest price in %d days: ' sprintf=[$OmnibuseufreeNumberOfDays] mod='omnibuseufree'}<span class="presta-studio-price-history-price">{$OmnibuseufreeProductPriceMin}</span>
@@ -29,3 +29,22 @@
</p>
</div>
{/if}
{if isset($OmnibuseufreeDebugEnabled) && $OmnibuseufreeDebugEnabled && isset($OmnibuseufreeDebugData)}
<div class="presta-studio-price-history" style="margin-top:6px;">
<p class="presta-studio-price-history-text" style="font-size:12px; line-height:1.35;">
<strong>OMNIBUS DEBUG</strong><br>
marker: {$OmnibuseufreeDebugData.marker}<br>
product_id: {$OmnibuseufreeDebugData.product_id}, attr_id: {$OmnibuseufreeDebugData.product_attribute_id}<br>
currency: {$OmnibuseufreeDebugData.currency_iso} ({$OmnibuseufreeDebugData.currency_id}), precision: {$OmnibuseufreeDebugData.price_display_precision}<br>
precision_override: {$OmnibuseufreeDebugData.display_precision_override}<br>
has_discount: {$OmnibuseufreeDebugData.has_discount}<br>
param price: {$OmnibuseufreeDebugData.param_price}<br>
param price_amount: {$OmnibuseufreeDebugData.param_price_amount}<br>
param regular_price: {$OmnibuseufreeDebugData.param_regular_price}<br>
computed fallback: {$OmnibuseufreeDebugData.computed_fallback}<br>
computed minimal: {$OmnibuseufreeDebugData.computed_minimal}<br>
forced_fallback_no_pre_discount_history: {$OmnibuseufreeDebugData.forced_fallback_no_pre_discount_history}
</p>
</div>
{/if}