Question

We have simple catalog price rule which is valid indefinitely.

In our Google Shopping feed which is generated at midnight, the price rule does not apply.

My theory is, that there is a small time frame, where the calculated prices are not available.

I have checked catalogrule_product_price - there seem to be only prices calculated until today (2013-04-22), so they would expire at midnight:

mysql> select distinct rule_date from catalogrule_product_price;
+------------+
| rule_date  |
+------------+
| 2013-04-20 |
| 2013-04-21 |
| 2013-04-22 |
+------------+
3 rows in set (0.05 sec)

Is this normal? cron_schedule has recent entries so I think the cron system is generally running.

I was having in mind, that price rules are always generated several days in advance, just to avoid such time spans with wrong prices - was I wrong with this assumption? What is going on here?

EDIT: checked it again today (2013-04-25) - same problem. I wish I checked it yesterday to see if also 23.,24. and 25. where existing and so the prices are generated always in bunches or tree of if the prices are always generated until today and three days back.

mysql> select distinct rule_date from catalogrule_product_price;
+------------+
| rule_date  |
+------------+
| 2013-04-23 |
| 2013-04-24 |
| 2013-04-25 |
+------------+
3 rows in set (0.00 sec)
Was it helpful?

Solution

No.

The cron job calls the observer method Mage_CatalogRule_Model_Observer::dailyCatalogUpdate(). This one calls Mage_CatalogRule_Model_Resource_Rule::applyAllRulesForDateRange() without arguments.

If applyAllRulesForDateRange() is called without arguments, one day +/- the current date is assumed.

So you can create newer or older dates but the nightly cron job does not.

OTHER TIPS

I spend sometime to understand this :)

And The script calculate prices for the current day, the previous day and the next day.

In Which, Updates include interval 3 days [in Magento 2.2.X]

  • current day - 1 days before + 1 days after

Daily update catalog price rule by cron

/vendor/magento/module-catalog-rule/Cron/DailyCatalogUpdate.php

  • Update include interval 3 days - current day - 1 days before + 1 days after
  • This method is called from cron process, cron is working in UTC time and
  • we should generate data for interval -1 day ... +1 day

Reindex product prices according rule settings.

/vendor/magento/module-catalog-rule/Model/Indexer/ReindexRuleProductPrice.php

public function execute(
    $batchCount,
    \Magento\Catalog\Model\Product $product = null,
    $useAdditionalTable = false
) {
    $fromDate = mktime(0, 0, 0, date('m'), date('d') - 1);
    $toDate = mktime(0, 0, 0, date('m'), date('d') + 1);

    /**
     * Update products rules prices per each website separately
     * because of max join limit in mysql
     */

    -
    -
    -

$ruleData['from_time'] = $this->roundTime($ruleData['from_time']);
$ruleData['to_time'] = $this->roundTime($ruleData['to_time']);
/**
 * Build prices for each day
 */
for ($time = $fromDate; $time <= $toDate; $time += IndexBuilder::SECONDS_IN_DAY) {
    if (($ruleData['from_time'] == 0 ||
            $time >= $ruleData['from_time']) && ($ruleData['to_time'] == 0 ||
            $time <= $ruleData['to_time'])
    ) {
        $priceKey = $time . '_' . $productKey;

        if (isset($stopFlags[$priceKey])) {
            continue;
        }

        if (!isset($dayPrices[$priceKey])) {
            $dayPrices[$priceKey] = [
                'rule_date' => $time,
                'website_id' => $ruleData['website_id'],
                'customer_group_id' => $ruleData['customer_group_id'],
                'product_id' => $ruleProductId,
                'rule_price' => $this->productPriceCalculator->calculate($ruleData),
                'latest_start_date' => $ruleData['from_time'],
                'earliest_end_date' => $ruleData['to_time'],
            ];
        } else {
            $dayPrices[$priceKey]['rule_price'] = $this->productPriceCalculator->calculate(
                $ruleData,
                $dayPrices[$priceKey]
            );
            $dayPrices[$priceKey]['latest_start_date'] = max(
                $dayPrices[$priceKey]['latest_start_date'],
                $ruleData['from_time']
            );
            $dayPrices[$priceKey]['earliest_end_date'] = min(
                $dayPrices[$priceKey]['earliest_end_date'],
                $ruleData['to_time']
            );
        }

        if ($ruleData['action_stop']) {
            $stopFlags[$priceKey] = true;
        }
    }
}

So the calculation duration

$fromDate = mktime(0, 0, 0, date('m'), date('d') - 1);
$toDate = mktime(0, 0, 0, date('m'), date('d') + 1);

In Magento 1.X this bug occurs if you are living in a timezone which is more than +01:00 from GMT. The default cronjob is running at 01:00 and is using GMT time to set the rule_date. In said case the date will be "yesterday" so there would be no price rule for the current day.

Example:

Current Datetime: 2017-07-19 01:00:00 (at current timezone)
Current Datetime at GMT: 2017-07-18 23:00:00
At 01:00 cronjob runs to write price rules with "$coreDate->gmtTimestamp('Today');"
Function will return "2017-07-18" which in this example is "yesterday"

Solution in 2.2.X

/vendor/magento/module-catalog-rule/Model/Indexer/IndexBuilder.php

$fromTime = strtotime($rule->getFromDate());
$toTime = strtotime($rule->getToDate());
$toTime = $toTime ? $toTime + self::SECONDS_IN_DAY - 1 : 0;

References

  1. http://www.divisionlab.com/solvingmagento/magento-catalog-price-rules/
  2. https://github.com/magento/magento2/issues/6610
  3. https://ipfs-sec.stackexchange.cloudflare-ipfs.com/magento/A/question/3161.html
  4. https://support.google.com/merchants/answer/6069284?hl=en
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top