Showing posts with label website. Show all posts
Showing posts with label website. Show all posts

Tuesday, January 29, 2013

Share cart between websites

I saw that this is a general issue among Magneto users/developers.
Here is how I was able to keep the cart between websites.
The solution is not fully tested yet but for me it seams to work.
[Update]
Warning: I seams that this solution doesn't work with multiple currencies installed. See comments from MichaƂ Burda
[/Update]
If someone tries it please let me know the result and eventual bugs that appear.
Preconditions:
  • 'Use SID on Frontend' must be st to 'Yes' (System->Configuration->Web->Session Validation Settings)
Approach:
Magneto already allows you to keep the quote (cart) between store views from the same website.
I tried to manipulate this feature into letting me keep the cart between all websites (store views).
How is the quote kept in $_SESSION?
Magento keeps the quote id in the $_SESSION like this:
$_SESSION['quote_id_5'] = 34;
In the code above, 34 represents the quote id and 5 represents the website it (not store view id).
So it's basically like this:
$_SESSION['quote_id_{WEBSITE_ID}'] = {QUOTE_ID};
This means that the quote is different for each website.
Now for the actual code:
I've created a new extension called Easylife_Sales.
The extension has a fail-safe, in case it doesn't work as expected, it's behavior can be disabled from the configuration area. but more on this later.
Extension files:
app/etc/modules/Easylife_Sales.xml - declaration file
<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Sales>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
             <Mage_Sales /><!-- so it's loaded after Mage_Sales -->
             <Mage_Checkout /><!-- so it's loaded after Mage_Checkout -->
            </depends>
        </Easylife_Sales>
    </modules>
</config>
app/code/local/Easylife/Sales/etc/config.xml - configuration file
<?xml version="1.0"?>
<config>
 <modules>
  <Easylife_Sales>
   <version>0.0.1</version>
  </Easylife_Sales>
 </modules>
 <global>
  <models>
   <sales>
    <rewrite>
     <observer>Easylife_Sales_Model_Observer</observer>
     <quote>Easylife_Sales_Model_Quote</quote>
    </rewrite>
   </sales>
   <checkout>
    <rewrite>
     <session>Easylife_Sales_Model_Checkout_Session</session>
    </rewrite>
   </checkout>
  </models>
  <helpers>
   <sales>
    <rewrite>
     <data>Easylife_Sales_Helper_Data</data>
    </rewrite>
   </sales>
  </helpers>
 </global>
 <frontend>
  <events><!-- this section is not mandatory, explanations later -->
   <sales_quote_collect_totals_before>
    <observers>
     <easylife_sales>
      <class>sales/observer</class>
      <method>checkProductAvailability</method>
     </easylife_sales>
    </observers>
   </sales_quote_collect_totals_before>
  </events>
 </frontend>
 <default>
  <checkout>
   <options>
    <persistent_quote>1</persistent_quote><!-- this is for the fail-safe -->
   </options>
  </checkout>
 </default>
</config>
app/code/local/Easylife/Sales/Helper/Data.php - override the default sales helper to add the fail-save method
<?php 
class Easylife_Sales_Helper_Data extends Mage_Sales_Helper_Data{
    public function getIsQuotePersistent(){
  return Mage::getStoreConfigFlag('checkout/options/persistent_quote');
 }
}
app/code/local/Easylife/Sales/Model/Checkout/Session.php - override the default checkout session in order to change the session key for the quote
<?php 
class Easylife_Sales_Model_Checkout_Session extends Mage_Checkout_Model_Session{
 protected function _getQuoteIdKey()
    {
     if (Mage::helper('sales')->getIsQuotePersistent()){//if behavior is not disabled
         return 'quote_id';
     }
     return parent::_getQuoteIdKey();
    }
}
app/code/local/Easylife/Sales/Model/Quote.php - override the quote model to share between all websites
<?php 
class Easylife_Sales_Model_Quote extends Mage_Sales_Model_Quote{
 public function getSharedStoreIds(){
  if (Mage::helper('sales')->getIsQuotePersistent()){//if behavior is not diasabled
   $ids = Mage::getModel('core/store')->getCollection()->getAllIds();
   unset($ids[0]);//remove admin just in case
   return $ids;
  }
  return parent::getSharedStoreIds();
 }
}
app/code/local/Easylife/Sales/etc/system.xml - this allows you do disable the functionality in case something is wrong.
<?xml version="1.0"?>
<config>
 <sections>
  <checkout>
   <groups>
    <options>
     <fields>
      <persistent_quote translate="label" module="sales">
       <label>Keep cart between websites</label>
       <frontend_type>select</frontend_type>
       <source_model>adminhtml/system_config_source_yesno</source_model>
       <sort_order>100</sort_order>
       <show_in_default>1</show_in_default>
       <show_in_website>0</show_in_website>
       <show_in_store>0</show_in_store>
      </persistent_quote>
     </fields>
    </options>
   </groups>
  </checkout>
 </sections>
</config>
We are almost done. At this point the following happens. If you have a product in cart, you change the website and the product is not available in the new site the product is still in the cart. If you want this behavior then there is no problem. All you need to do is to remove these lines from config.xml
<observer>Easylife_Sales_Model_Observer</observer>
and
<events><!-- this section is not mandatory, explanations later -->
 <sales_quote_collect_totals_before>
  <observers>
   <easylife_sales>
    <class>sales/observer</class>
    <method>checkProductAvailability</method>
   </easylife_sales>
  </observers>
 </sales_quote_collect_totals_before>
</events>
In my case I wanted to remove from cart (permanently) the products that are not available in that website. if you want this behavior add the following file: app/code/local/Easylife/Sales/Model/Observer.php - this will remove from cart the products that are not valid on the current store.
<?php 
class Easylife_Sales_Model_Observer extends Mage_Sales_Model_Observer{
        public function checkProductAvailability($observer){
  if (!Mage::helper('sales')->getIsQuotePersistent()){
   return $this;
  }
  $quote = $observer->getEvent()->getQuote();
  $currentId = Mage::app()->getWebsite()->getId();
  
  $messages = array();
  
  foreach ($quote->getAllItems() as $item){   
   $product = $item->getProduct();
   if (!in_array($currentId, $product->getWebsiteIds())){
    $quote->removeItem($item->getId());
    $messages[] = Mage::helper('catalog')->__('Product %s is not available on website %s', $item->getName(), Mage::app()->getWebsite()->getName());
   }
  }
  foreach ($messages as $message){
   Mage::getSingleton('checkout/session')->addError($message);
  }
  return $this;
 }
}
Well that's about it. Enjoy and let me know how it turns out.

Marius.

Monday, December 28, 2009

Switching language and currency when having multiple websitecodes (for sonician)

Problem (and maybe better solutions) found here:
http://www.magentocommerce.com/boards/viewthread/71171/

Hi again
There is a way of running a store view directly.
When you call something like this:
Mage::run('website1', 'website');
the default store view from website1 will run.
Let's say in website1 you have a store view called store_view_1. You can run it like this.
Mage::run('store_view_1');
As for the currency, you can set a default currency for each store view.
For example you can have to identical store views (in English), one with default currency 'EUR' and one 'GBP'.
Let's say the first one is called store_view_eur, and the second one store_view_gbp.
You can run them like this.
if (some condition){
Mage::run('store_view_eur');
}
else{
Mage::run('store_view_gbp');
}
As for the IP location, sorry but I don't think I can help you much there.

Thursday, December 24, 2009

Websitecode, currency, language (for sonician)

Problem:
get through code the current values for website, currency and language.
Hello,
Website:
//for name
Mage::app()->getWebsite()->getName();
//for code
Mage::app()->getWebsite()->getCode();
Currency:
Mage::app()->getStore()->getCurrentCurrencyCode();
Language:
This is a little tricky. You can get the ISO code for the language, because by standards French for France is different from French for Belgium
Mage::app()->getLocale()->getLocale();//will return something like fr_FR, fr_BE or en_US
if you want to go further and see only the language code it's simple
$isoCode = Mage::app()->getLocale()->getLocale();
$parts = explode("_", $isoCode);
$language = $parts[0];
$country = $parts[1];

Monday, November 23, 2009

Link customer login to store view? (for Pulse Digital Ltd)

This is a response for http://www.magentocommerce.com/boards/viewthread/67624/
Problem: Limit customers to only one store view.

I don't think you can limit a customer to a single store view, and limit his access only to that store view.
The whole idea of store view is that you have multiple versions (languages or currencies) for the same website.
What you can do is to set up 2 (or more) websites, each one with specific prices and/or products and allow the customer to access only that website.
You can find a tutorial here http://www.magentocommerce.com/knowledge-base/entry/overview-how-multiple-websites-stores-work and in the videos reffered here.
For example you set up mysite.com and mysite.eu. They can be hosted on the same machine and moderated form the same admin panel.
After that you can choose not to share the customer accounts from System->configuration->Customer configuration.
In the "Account Sharing Options" section set "Share Customer Accounts" to "Per Website".