5

How do I apply coupon codes for newly registered customers only in Magento 1.9?

  • How u define a customer is New Registered ? – Amit Bera Feb 8 '16 at 4:52
  • 1
    @AmitBera New Registered means he registered to site & he didt placed any order, when first time he is trying to place an order, only at that time coupon code should work.... – Baby in Magento Feb 3 '17 at 11:19
15
+50

I'll create a module which does this in order to give more insight into how it's done. We're going to use setup scripts (for attribute setup), event observers, condition model and a helper class.

I'm assuming you know basics of how modules work/are done in Magento so I'll skip some of the code in the answer to make it shorter and post it as a public repository.

  • Example namespace: Versedi
  • Example module name: NewCustomerCoupon

Files structure

  1. First create a directory/files structure as following

    app/etc/modules/NameSpace_Module.xml
    app/code/local/NameSpace/Module/etc/config.xml
    app/code/local/NameSpace/Module/Model/Observer.php
    app/code/local/NameSpace/Module/Helper/Data.php
    app/code/local/NameSpace/Module/Model/Rule/Condition/Customer/NewCustomer.php
    app/code/local/NameSpace/Module/sql/namespace_module_setup/install-1.0.0.php
    

Module configuration

Events

  1. In modules configuration file app/code/local/NameSpace/Module/etc/config.xml we need to declare the events observers. We're doing it in global node cause that customer may place order in frontend as well as in backend through eg. phone

We need to use three events:

  1. customer_register_success - to set the attribute is_customer_new to 1, (area: frontend)

  2. sales_order_place_after - to set the attribute is_customer_new to 0, (area: global)

  3. salesrule_rule_condition_combine - to create custom condition in Shopping Cart Price Rules > Conditions (area: adminhtml)

    <global>....
    <events>
            <sales_order_place_after>
                <observers>
                    <versedi_newcustomercoupon_customer_placed_order>
                        <class>Versedi_NewCustomerCoupon_Model_Observer</class>
                        <type>singleton</type>
                        <method>orderPlaced</method>
                    </versedi_newcustomercoupon_customer_placed_order>
                </observers>
            </sales_order_place_after>
        </events>
    

    model Versedi_NewCustomerCoupon_Model_Observer addCustomerCondition Versedi_NewCustomerCoupon_Model_Observer singleton customerRegistered

Setup script

Under global node we have to define that while installing module setup scripts are supposed to be searched for. Under global node add block:

<resources>
        <versedi_newcustomercoupon_setup> <!-- directory name in sql directory of module path -->
            <setup>
                <module>Versedi_NewCustomerCoupon</module>
                <class>Mage_Catalog_Model_Resource_Setup</class>
            </setup>
        </versedi_newcustomercoupon_setup>
  </resources>

Attention! The node called versedi_newcustomercoupon_setup must be exactly same as your directory name inside sql installer directory. Files inside must be named install-VERSION_NUMBER.php (fg. install-1.0.0) for installations and upgrade-VERSION_NUMBER.php (fg. upgrade-1.5.6.php) where the version number defined in etc/config.xml must be exact same or higher than the installer's script filename.

Module setup - creating attribute

  1. Now let's create our attribute. Open up installer file at:

    app/code/local/Versedi/NewCustomerCoupon/sql/versedi_newcustomercoupon_setup/install-1.0.0.php

I won't go into many details why and how installer works, you can find enough details about it on the web. Only detail I'd like to point out is that we first have to add the attribute, and after that load it and add it to adminhtml_customer form and set it's possition in it. I think the rest is almost self-explanatory, if not then read about installer scripts and creating attributes programmaticaly.

<?php
$installer = $this;
/* @var $installer Mage_Core_Model_Resource_Setup */

$installer->startSetup();
$attribute = array(
    'attribute_model' => null,
    'backend'         => null,
    'type'            => 'int',
    'table'           => null,
    'frontend'        => null,
    'input'           => 'select',
    'label'           => 'New customer (placed no orders yet)',
    'frontend_class'  => '',
    'source'          => 'eav/entity_attribute_source_boolean',
    'required'        => '0',
    'is_user_defined' => '1',
    'default'         => '0',
    'unique'          => '0',
    'note'            => null,
    'visible'         => '0',
    'input_filter'    => null,
    'multiline_count' => '1',
    'validate_rules'  => null,
    'system'          => '0',
    'data_model'      => null,
);
$entityTypeId = $installer->getEntityTypeId('customer');
$installer->addAttribute($entityTypeId, 'is_customer_new', $attribute);

//Now we can add it to form and set it's sort order.

$forms = array('adminhtml_customer');
$attr = Mage::getSingleton('eav/config')->getAttribute($entityTypeId, 'is_customer_new');
$attr->setUsedInForms($forms);
$attr->setSortOrder(999);
try {
    $attr->save();
} catch (Exception $e) {
    Mage::logException($e);
}
$installer->endSetup();

Creating event observers

  1. Now we're going to define our observer class and it's methods.

Open app/code/local/Versedi/NewCustomerCoupon/Model/Observer.php

We've previously defined in module's config file that when customer registers a method called customerRegistered will be called:

    public function customerRegistered(Varien_Event_Observer $observer) {
        $customer = $observer->getCustomer();
        $customer->setIsCustomerNew(1)->save();

        return $this;
    }

Then when order is placed in global area (both adminhtml and frontend) then we need to call the method orderPlaced:

    public function orderPlaced(Varien_Event_Observer $observer) {
        $customer = $observer->getOrder()->getCustomer();
        $customer->setIsCustomerNew(0)->save();

        return $this;
    }

And the last one for adminhtml area - which's responsible for inserting our custom condition to existing conditions addCustomerConditions:

    public function addCustomerCondition(Varien_Event_Observer $observer) {

        $conditions = array(
            array(
                'value' => 'versedi_newcustomercoupon/rule_condition_customer_newCustomer',
                'label' => Mage::helper('versedi_newcustomercoupon')->__('Is Customer New'),
            ),
        );

        $additional = $observer->getEvent()->getAdditional();
        $additional->setConditions($conditions);

        return $this;

    }
}

Last thing is to update the class responsible for our condition logic. The class was assigned to this condition in above block code under value key in $conditions array: versedi_newcustomercoupon/rule_condition_customer_newCustomer This class is pretty much same thing as core class Mage_SalesRule_Model_Rule_Condition_Product_Found - both have same logic, they only differ with the strings displayed on screen.

Such class must define following methods: __construct - which's setting the type that I've mentioned above.

 public function __construct() {
    parent::__construct();
    $this->setType('versedi_newcustomercoupon/rule_condition_customer_newCustomer');
}

loadValueOptions - responsible for setting the value option. Since the created attribute is type of int, we'll call setValueOption in it in following way:

 /**
 * Load value options
 *
 * @return Versedi_NewCustomerCoupon_Model_Rule_Condition_Customer_NewCustomer
 */
public function loadValueOptions() {
    $this->setValueOption(array(
        1 => Mage::helper('versedi_newcustomercoupon')->__('is new and placed no orders.'),
        0 => Mage::helper('versedi_newcustomercoupon')->__('already placed orders in the past.'),
    ));

    return $this;
}

asHtml - responsible for returning string containing html for value choosing:

public function asHtml()
{
    $html = $this->getTypeElement()->getHtml() .
        Mage::helper('salesrule')->__("If customer %s", $this->getValueElement()
                                                                                                                                 ->getHtml());
    if ($this->getId() != '1') {
        $html .= $this->getRemoveLinkHtml();
    }

    return $html;
}

And the last one, most important validate, which returns true if the conditions is valid, and false if it's invalid.

    public function validate(Varien_Object $object) {
        return (bool)$object->getQuote()->getCustomer()->getIsCustomerNew();
    }

Now create a new shopping cart price rule and in condition tab do something like this:

Condition setting

This is pretty much everything. What could be added? A data upgrade script which would filter all customers that are already registered but didn't placed order yet when installing the module - these will be set with No since the is_customer_new field default=0

PS. As promised a repo: https://github.com/versedi/NewCustomerCoupon

| improve this answer | |
  • This is priceless answer, when you get free time, update this post with link to repository , you are champ buddy :) – Baby in Magento Feb 3 '17 at 19:10
  • 1
    I've edited the answer with link to repository. – versedi Feb 3 '17 at 19:22
  • 1
    you , github , mse , Joel Spolsky & Jeff Atwood => all are awesome :) – Baby in Magento Feb 3 '17 at 19:40
  • After installing this extension I started to get duplicated payment and that the email address is missing (error message) – Aboodred1 Jan 16 '19 at 17:39
3

You have to create a new customer Attribute ex - is_new_customer. Then when a customer registers successfully fire this event customer_register_success. If success then save 1 value to is_new_customer. And then during checkout when customer will place order with coupon code, Again fire an event for Order Success sales_order_place_after, and check in sales_flat_order table column coupon_code value. If that customer has used coupon then set Customer Attribute is_new_customer to 0.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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