0

we need an option in backend > attributes to set "timeout" for each product.

we want to display the timeout in view page.

something as below :

enter image description here

after the timeout ends, automaticlly Product status should become "Disable" in Backend.

4
  • For this case,you need to use cron . Cron Job To Disable Product Magento 1.7 CE
    – Amit Bera
    Commented May 9, 2016 at 12:10
  • @AmitBera it seems like tough job, i will try and let you know. Commented May 9, 2016 at 12:22
  • @AmitBera if we use cron then what will be cron expression as per your suggestion? Commented May 9, 2016 at 12:38
  • Set cron to run every minute also once the timer moves to zero you have to call an AJAX to update the product status as there will be users on the website that will be looking timer.
    – PHP Bugs
    Commented May 25, 2016 at 10:17

2 Answers 2

1

For UI, you can use one of these FREE extensions:

Then setup a CRON for checking timeout attribute and Disable product

1
  • it seems like tough job, i will try and let you know regarding cron. Commented May 9, 2016 at 12:22
0

credits for our boss: @R.S

From www.ecomdev.org (page no longer exist)

Introduction This article will help you to understand basic customizations for catalog products and performing custom cron jobs in Magento.

Functionality Before start the development you should imagine what it does and choose the functionality that fits all the requirements.

The requirements for the module are the following:

  • It should allow an admin user to specify the activation and expiration dates for a product.

  • It should check products for the specified dates and perform the following actions depend on the date types:

    • Active the product if the activation date came true
    • Active the product if the expiry date came true

So the module development should follow these steps:

  1. Create a custom attribute back-end model to allow storing date for datetime attribute (Magento native eav implementation removes the time part from a datetime string)

  2. Create two attributes for a product, that might be fulfilled with activation and expiry dates and assign custom attribute backend model to them Create an event observer that should handle product edit block rendering to enable time specifying for the date fields Create a cron job that checks the activation and expiry dates for products and enables/disables them

Basic Structure

Now you know how it should work, so you can create a basic module structure.

The structure of the module should contain the following:

  • the module bootstrap and main configuration files
  • an SQL upgrade script for the attributes adding and a setup model
  • the event observer class that also will contain the cron job
  • the custom attribute backend model

You should name the module before its structure creation. The module name consists of the module namespace and an internal module name separated by the underscore sign. So the name of this module will be “EcomDev_ScheduledProduct”, where “EcomDev” it’s my extension namespace.

First of all you should create the module bootstrap configuration file to enable your module. Bootstrap files located in “app/etc/modules” folder. The name of file should be the same as the module name. So you should create file “EcomDev_ScheduledProduct.xml”, the file structure should contain the module name, its code pool, activity state and dependence node for specifying of required modules. So it should be like the following:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <EcomDev_ScheduledProduct>
            <active>true</active> <!-- the module activity state -->
            <codePool>community</codePool> <!-- the module code pool -->
            <depends>
                <Mage_Catalog />  <!-- the module depends on Mage_Catalog module, so it mentioned here -->
            </depends>
        </EcomDev_ScheduledProduct>
    </modules>
</config>

The module was specified to be placed in community code pool, so it should be placed in “app/code/community” folder and its path should be “app/code/community/EcomDev/ScheduledProduct”.

Now you should create the module configuration file, where you’ll specify the model namespace and setup script initialization statements.

Let’s create it: “app/code/community/EcomDev/ScheduledProduct/etc/config.xml”

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <EcomDev_ScheduledProduct>
            <version>1.0.0</version>
        </EcomDev_ScheduledProduct>
    </modules>
    <global>
        <models>
            <ecomdev_scheduledproduct>
            <!-- specification of model name space,
                 so we can call models like Mage::getModel('ecomdev_scheduledproduct/somemodelname') -->
                <class>EcomDev_ScheduledProduct_Model</class>
            </ecomdev_scheduledproduct>
        </models>
        <resources>
            <!-- specifying of setup model and setup script path in sql folder -->
            <ecomdev_scheduledproduct_setup>
                <setup>
                    <module>EcomDev_ScheduledProduct</module>
                    <class>EcomDev_ScheduledProduct_Model_Mysql4_Setup</class>
                </setup>
                <connection>
                    <!-- use catalog connection to modify products -->
                    <use>catalog_setup</use>
                </connection>
            </ecomdev_scheduledproduct_setup>
        </resources>
    </global>
</config>

Attribute Backend Model Before creation of setup script you need to take care of datetime attribute backend model to specify it in setup. Create it in module “Model” folder. In this module you should call it “EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime”, the path “Attribute_Backend_Datetime” explains what the model does. In it you should override “beforeSave($object)”, “afterLoad($object)” and “formatDate($date)” methods to change the logic of your attributes storage. You might like also to add “compareDateToCurrent($date)” method to check activation or expiration date came true before product save. The model should be extended from “Mage_Eav_Model_Entity_Attribute_Backend_Datetime”. “app/code/community/EcomDev/ScheduledProduct/Model/Attribute/Backend/Datetime.php”

<?php
/**
 * Expiry and Activation dates custom backend model
 *
 */
class EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime extends Mage_Eav_Model_Entity_Attribute_Backend_Datetime
{
    /**
     * Activation date attribute code
     *
     * @var string
     */
    const ATTRIBUTE_ACTIVATION_DATE = 'ecomdev_activation_date';
    /**
     * Expiry date attribute code
     *
     * @var string
     */
    const ATTRIBUTE_EXPIRY_DATE = 'ecomdev_expiry_date';
    /**
     * Status attribute code
     *
     * @var string
     */
    const ATTRIBUTE_STATUS = 'status';
    /**
     * Checks date to update product status
     * on the save in the admin panel
     *
     * @param Mage_Catalog_Model_Product $object
     * @return EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime
     */
    public function beforeSave($object)
    {
        parent::beforeSave($object);
        $code = $this->getAttribute()->getAttributeCode();
        $compareResult = $this->compareDateToCurrent($object->getData($code));
        if ($compareResult !== false) {
            // If the date is set
            if (($compareResult < 0 && $code == self::ATTRIBUTE_ACTIVATION_DATE) ||
                ($compareResult >= 0 && $code == self::ATTRIBUTE_EXPIRY_DATE)) {
                // If the date is in the past and it's activation date
                // or the date is in the future and it's expiry date,
                // so the product should be deactivated
                $object->setData(
                    self::ATTRIBUTE_STATUS,
                    Mage_Catalog_Model_Product_Status::STATUS_DISABLED
                );
            }
        }
        return $this;
    }
    /**
     * Magento native function doesn't save
     * the time part of date so the logic of retrieving is changed
     *
     * @param   string|int $date
     * @return  string|null
     */
    public function formatDate($date)
    {
        if (empty($date)) {
            return null;
        } elseif (!($date instanceof Zend_Date)) {
            // Parse locale representation of the date, eg. parse user input from date field
            $dateString = $date;
            $usedDateFormat = Mage::app()->getLocale()->getDateTimeFormat(
                Mage_Core_Model_Locale::FORMAT_TYPE_SHORT
            );
            // Instantiate date object in current locale
            $date = Mage::app()->getLocale()->date();
            $date->set($dateString, $usedDateFormat);
        }
        // Set system timezone for date object
        $date->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE);
        return $date->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
    }
    /**
     * Compare date to current date
     *
     * Returns -1 if the date is in the past, and 1 if it's in the future,
     * returns 0 if the dates are equal.
     *
     * @param string $date
     * @return int
     */
    public function compareDateToCurrent($date)
    {
        if (empty($date)) {
            return false;
        }
        $compareDate = Mage::app()->getLocale()->date($date, Varien_Date::DATETIME_INTERNAL_FORMAT);
        $currentDate = Mage::app()->getLocale()->date();
        return $currentDate->compare($compareDate);
    }
    /**
     * Converts timezone after object load, fixes issue in the core form element
     *
     * @param Mage_Core_Model_Abstract $object
     * @return EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime
     */
    public function afterLoad($object)
    {
        $code = $this->getAttribute()->getAttributeCode();
        if ($object->getData($code) && !($object->getData($code) instanceof Zend_Date)) {
            $date = Mage::app()->getLocale()->date();
            $dateString = $object->getData($code);
            $currentTimezone = $date->getTimezone();
            $date->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE);
            $date->set($dateString, Varien_Date::DATETIME_INTERNAL_FORMAT);
            $date->setTimezone($currentTimezone);
            $object->setData($code, $date);
        }
        return parent::afterLoad($object);
    }
}

Setup Now you need to create setup model and setup script. In the configuration file, the setup model class name is “EcomDev_ScheduledProduct_Model_Mysql4_Setup”. The module extends the catalog functionality, so the module setup model extends from the catalog setup model. “app/code/community/EcomDev/ScheduledProduct/Model/Mysql4/Setup.php”

<?php
/**
 * Setup model for scheduled product module, extended from catalog module setup
 */
class EcomDev_ScheduledProduct_Model_Mysql4_Setup extends Mage_Catalog_Model_Resource_Eav_Mysql4_Setup
{
}

And you need to create the setup script in “sql/ecomdev_scheduledproduct_setup” folder. The module version is 1.0.0 and it’s actually the first version, so you need to name it “mysql4-install-1.0.0.php”. This script should contain adding of the attributes to EAV. Also for this module we should add columns to “catalog_product_entity” table, because it will speed up the product mass status update process. “app/code/community/EcomDev/ScheduledProduct/sql/ecomdev_scheduledproduct_setup/mysql4-install-1.0.0.php”

<?php
/* @var $this EcomDev_ScheduledProduct_Model_Mysql4_Setup */
$this->startSetup();
// For performance reasons we should add this fields to main entity table
// Activation date column adding to product entity table
$this->getConnection()->addColumn(
    $this->getTable('catalog/product'),
    EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
    'DATETIME DEFAULT NULL'
);
// Expiry date column adding to product entity table
$this->getConnection()->addColumn(
    $this->getTable('catalog/product'),
    EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
    'DATETIME DEFAULT NULL'
);
// Activation date attribute information adding to the product entity
$this->addAttribute(
    'catalog_product',
    EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
    array(
        'type'      => 'static',
        'input'     => 'date',
        'label'     => 'Activation Date',
        'global'    => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
        'backend'   => 'ecomdev_scheduledproduct/attribute_backend_datetime',
        'visible'   => 1,
        'required'  => 0,
        'position'  => 10,
        'group'     => 'Schedule Settings'
    )
);
// Expiry date attribute information adding to the product entity
$this->addAttribute(
    'catalog_product',
    EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
    array(
        'type'      => 'static',
        'input'     => 'date',
        'label'     => 'Expiry Date',
        'global'    => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
        'backend'   => 'ecomdev_scheduledproduct/attribute_backend_datetime',
        'visible'   => 1,
        'required'  => 0,
        'position'  => 20,
        'group'     => 'Schedule Settings'
    )
);
$this->endSetup();

Event Observer After creation of the setup script and the back-end model, you need to take care about the input field rendering for the attributes, that’s why you need to observe “adminhtml_catalog_product_edit_prepare_form” event. So you should create “EcomDev_ScheduledProduct_Model_Observer” class with “observeProductEditFortInitialization(Varien_Event_Observer $observer)” method. It should check the form object for elements with the date attributes code and add datetime format to them if found any.

<?php
/**
 * Observer for core events handling
 *
 */
class EcomDev_ScheduledProduct_Model_Observer
{
    /**
     * Observes event 'adminhtml_catalog_product_edit_prepare_form'
     * and adds custom format for date input
     *
     * @param Varien_Event_Observer $observer
     * @return void
     */
    public function observeProductEditFortInitialization(Varien_Event_Observer $observer)
    {
        $form = $observer->getEvent()->getForm();
        $elementsToCheck = array(
            EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
            EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE
        );
        foreach ($elementsToCheck as $elementCode) {
            $element = $form->getElement($elementCode);
            if (!$element) {
                continue;
            }
            $element->setFormat(
                Mage::app()->getLocale()->getDateTimeFormat(
                    Mage_Core_Model_Locale::FORMAT_TYPE_SHORT
                )
            );
            $element->setTime(true);
        }
    }
}

Also you need to define your event observer in the module configuration file (config.xml):

<config>
    <!-- here goes the code you've created before
          ...
          ...
      -->
    <adminhtml>
        <events>
            <adminhtml_catalog_product_edit_prepare_form>
                <observers>
                    <ecomdev_scheduledproduct>
                        <type>singleton</type>
                        <model>ecomdev_scheduledproduct/observer</model>
                        <method>observeProductEditFortInitialization</method>
                    </ecomdev_scheduledproduct>
                </observers>
            </adminhtml_catalog_product_edit_prepare_form>
        </events>
    </adminhtml>
</config>

Cron Job When you’ve done with setting up the admin interface for your attributes you need to create a cron job that automatically activates/deactivates products. You can put the logic in “EcomDev_ScheduledProduct_Model_Observer” class, because realization of cron job processing calls is similar to event processing, except you wont get $observer argument.

<?php
/**
 * Observer for core events handling and cron jobs processing
 *
 */
class EcomDev_ScheduledProduct_Model_Observer
{
    /*
     * here goes the code you've created before
     * ............
     * ............
     */
    /**
     * Cron job for processing of scheduled products
     *
     * @return void
     */
    public function cronProcessScheduledProducts()
    {
        $currentDate = Mage::app()->getLocale()->date()->toString(
            Varien_Date::DATETIME_INTERNAL_FORMAT
        );
        $productModel = Mage::getModel('catalog/product');
        /* @var $expiredProductsCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
        // Prepare collection of scheduled for expiry but haven't yet deactivated products
        $expiredProductsCollection = $productModel->getCollection()
            // Add filter for expired but products haven't yet deactivated
            ->addFieldToFilter(
                EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
                array(
                    'nnull' => 1,  // Specifies that date shouldn't be empty
                    'lteq' => $currentDate // And lower than current date
                )
            )
            ->addFieldToFilter(
                EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_STATUS,
                Mage_Catalog_Model_Product_Status::STATUS_ENABLED
            );
        // Retrieve product ids for deactivation
        $expiredProductIds = $expiredProductsCollection->getAllIds();
        unset($expiredProductsCollection);
        if ($expiredProductIds) {
            Mage::getSingleton('catalog/product_action')
                ->updateAttributes(
                         $expiredProductIds,
                         array('status' => Mage_Catalog_Model_Product_Status::STATUS_DISABLED),
                         Mage_Core_Model_App::ADMIN_STORE_ID
                );
        }
        /* @var $expiredProductsCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
        // Prepare collection of scheduled for activation but haven't yet activated products
        $activatedProductsCollection = $productModel->getCollection()
            ->addFieldToFilter(
                EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_ACTIVATION_DATE,
                array(
                    'nnull' => 1, // Specifies that date shouldn't be empty
                    'lteq' => $currentDate // And lower than current date
                )
            )
            // Exclude expired products
            ->addFieldToFilter(
                EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_EXPIRY_DATE,
                array(
                    array('null' => 1), // Specifies that date shouldn't be empty
                    array('gt' => $currentDate) // And greater than current date
                )
            )
            ->addFieldToFilter(
                EcomDev_ScheduledProduct_Model_Attribute_Backend_Datetime::ATTRIBUTE_STATUS,
                Mage_Catalog_Model_Product_Status::STATUS_DISABLED
            );
        // Retrieve product ids for activation
        $activatedProductIds = $activatedProductsCollection->getAllIds();
        unset($activatedProductsCollection);
        if ($activatedProductIds) {
            Mage::getSingleton('catalog/product_action')
                ->updateAttributes(
                         $activatedProductIds,
                         array('status' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED),
                         Mage_Core_Model_App::ADMIN_STORE_ID
                );
        }
    }
}

And of course you should define your cron job in the configuration file (config.xml):

<config>
    <!-- here goes the code you've created before
          ...
          ...
      -->
    <crontab>
        <jobs>
            <ecomdev_scheduledproduct_process_schedule>
                <schedule>
                    <!-- Schedule for every 5 minutes -->
                    <cron_expr>*/5 * * * *</cron_expr>
                </schedule>
                <run>
                    <model>ecomdev_scheduledproduct/observer::cronProcessScheduledProducts</model>
                </run>
            </ecomdev_scheduledproduct_process_schedule>
        </jobs>
    </crontab>
</config>

Result Now you should login to the admin panel, navigate “System -> Cache Management -> Flush Magento Cache” to enable your extension. You can find the fields you’ve created at “Catalog -> Manage Products -> Edit/Add Product” page in “Schedule Settings” tab. And don’t forget to setup Magento cron in your system crontab.

Conclusion Now you know how to create simple customization for catalog with using of cron jobs in Magento. The module presented here available at Magento Connect as free community extension: Scheduled Products

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.