Paypal Express + New Customer = no taxes applied and customer assigned to NOT LOGGED IN group in Magento

Recently I asked a question on Stackoverflow about a weird issue when using Paypal Express in Magento. If the customer is registered during the payment process, when the order is completed, the customer is not assigned to any group and no taxes are applied to the order.

I finally found the solution myself and like to post the fix in here. It is necessary to rewrite the class app/code/core/Mage/Paypal/Model/Express/Checkout.php and modify the method _prepareNewCustomerQuote() so that it assigns the customer to the correct group.

  • Class rewrite

Create a new module in local pool. The config.xml should look like this:

<?xml version="1.0"?>
<config>
    <modules>
        <YourModule_Paypal>
            <version>1.0.0</version>
        </YourModule_Paypal>
    </modules>
    <global>
        <models>
            <paypal>
                <rewrite>
                    <express_checkout>YourModule_Paypal_Model_Express_Checkout</express_checkout>
                </rewrite>
            </paypal>
        </models>
    </global>
</config>
  • Method modification

Here you have the whole code of how the class should be now. Please verify there are no new lines on the original class. This might differ depending on the Magento version (this comes from 1.7.0.2). Note that it’s only necessary to force the group assignation:

class YourModule_Paypal_Model_Express_Checkout extends Mage_Paypal_Model_Express_Checkout
{
    /**
     * REWRITE: We force the new customer assignation to the general group (1)
     * Prepare quote for customer registration and customer order submit
     * and restore magento customer data from quote
     *
     * @return Mage_Paypal_Model_Express_Checkout
     */
    protected function _prepareNewCustomerQuote()
    {
        $quote      = $this->_quote;
        $billing    = $quote->getBillingAddress();
        $shipping   = $quote->isVirtual() ? null : $quote->getShippingAddress();

        $customer = $quote->getCustomer();
        /** @var $customer Mage_Customer_Model_Customer */
        $customerBilling = $billing->exportCustomerAddress();
        $customer->addAddress($customerBilling);
        $billing->setCustomerAddress($customerBilling);
        $customerBilling->setIsDefaultBilling(true);
        if ($shipping && !$shipping->getSameAsBilling()) {
            $customerShipping = $shipping->exportCustomerAddress();
            $customer->addAddress($customerShipping);
            $shipping->setCustomerAddress($customerShipping);
            $customerShipping->setIsDefaultShipping(true);
        } elseif ($shipping) {
            $customerBilling->setIsDefaultShipping(true);
        }
        /**
         * @todo integration with dynamica attributes customer_dob, customer_taxvat, customer_gender
         */
        if ($quote->getCustomerDob() && !$billing->getCustomerDob()) {
            $billing->setCustomerDob($quote->getCustomerDob());
        }

        if ($quote->getCustomerTaxvat() && !$billing->getCustomerTaxvat()) {
            $billing->setCustomerTaxvat($quote->getCustomerTaxvat());
        }

        if ($quote->getCustomerGender() && !$billing->getCustomerGender()) {
            $billing->setCustomerGender($quote->getCustomerGender());
        }

        Mage::helper('core')->copyFieldset('checkout_onepage_billing', 'to_customer', $billing, $customer);
        $customer->setEmail($quote->getCustomerEmail());
        $customer->setPrefix($quote->getCustomerPrefix());
        $customer->setFirstname($quote->getCustomerFirstname());
        $customer->setMiddlename($quote->getCustomerMiddlename());
        $customer->setLastname($quote->getCustomerLastname());
        $customer->setSuffix($quote->getCustomerSuffix());
        $customer->setGroupId(Mage::getStoreConfig('customer/create_account/default_group')); //Force customer assignation to default group
        $customer->setPassword($customer->decryptPassword($quote->getPasswordHash()));
        $customer->setPasswordHash($customer->hashPassword($customer->getPassword()));
        $customer->save();
        $quote->setCustomer($customer);

        return $this;
    }
}

 

Cleaning Magento Logs in Database

Magento has a very nice script on the shell directory called “log.php”. You can do many things with it, these are the 2 most interesting ones for me:

Wiew the log data’s size

$ php log.php status
-----------------------------------+------------+------------+------------+
Table Name                         | Rows       | Data Size  | Index Size |
-----------------------------------+------------+------------+------------+
log_customer                       | 84.83K     | 4.73Mb     | 3.69Mb     |
log_visitor                        | 2.22M      | 185.83Mb   | 0 b        |
log_visitor_info                   | 2.30M      | 368.44Mb   | 0 b        |
log_url                            | 7.92M      | 429.72Mb   | 471.38Mb   |
log_url_info                       | 8.37M      | 1.41Gb     | 0 b        |
log_quote                          | 10.70K     | 1.33Mb     | 0 b        |
report_viewed_product_index        | 1.59M      | 93.96Mb    | 329.17Mb   |
report_compared_product_index      | 7          | 16.38Kb    | 81.92Kb    |
report_event                       | 1.82M      | 114.98Mb   | 271.50Mb   |
catalog_compare_item               | 7          | 16.38Kb    | 81.92Kb    |
-----------------------------------+------------+------------+------------+
Total                              | 24.31M     | 2.61Gb     | 1.08Gb     |
-----------------------------------+------------+------------+------------+

Clean log data based on a number of days:

$ php -f log.php clean --days 30

Magento 1.9/1.14 come with a new default theme… finally!

Magento had been using the same theme during years. It was cool at first… but time went on, web design changes and the initially cool theme ended up being something to get rid of as soon as you installed Magento from the scratch.

But this has finally changed and Magento CE 1.9 and EE 1.14 come with an updated theme, modern, nice, simple and… responsive!

Magento Theme 1.9/1.14

Magento Theme 1.9/1.14

Isn’t this cool? You can check it lively here. I’ve also find something interesting when browsing a product. When moving the mouse over the product image we get a zoom window that works pretty fine. I do remember this functionality on Magento EE edition, but not on CE one:

Product Image Zoom in Magento 1.9/1.14

Product Image Zoom in Magento 1.9/1.14

Besides this new brand responsive theme, I don’t see any major changes on this release (at least not at functionality level).

Easy management of Magento scheduled tasks: Magento Cron Scheduler

Today one of my colleagues shared a really nice extension with me: Magento Cron Scheduler.

This extension lets you easily list and manage all the scheduled tasks in Magento, it also shows the the processes that will run in the following hours and the ones that were already executed.

  • Available tasks. Shows the list of all the crons defined in Magento, showing also the periodicity and the model they call.
Available Tasks - Magento Cron Scheduler

Available Tasks – Magento Cron Scheduler

  • Scheduled tasks. Show the list of the tasks that will be executed during the next hours and also the tasks that have already been executed. It also includes the messages in case the already launched tasks return a message.
Scheduled tasks - Magento Cron Scheduler

Scheduled tasks – Magento Cron Scheduler

  • Timeline. Nice feature! It shows a timeline diagram showing which tasks will be executed during the day.
Timeline - Magento Cron Scheduler

Timeline – Magento Cron Scheduler

_____________

Download

Script to execute upgrade actions without flushing the cache in Magento

When having many different servers I have faced more than once issues related to module installation/upgrades. Here you have a quick script that upgrades all modules from terminal:

<?php
require_once "../app/Mage.php";
Mage::app('admin');

$begin = microtime(true);
Mage::log("Upgrade Begin-".$begin);

Mage_Core_Model_Resource_Setup::applyAllUpdates();
Mage_Core_Model_Resource_Setup::applyAllDataUpdates();

$end = microtime(true);
Mage::log("Upgrade End-".$end);
Mage::log("Duree : ".($end - $begin));

Search AutoComplete and Suggestions extension for Magento

I just wanted to share this awesome [Free] Magento extension that modifies the quick search box by:

  • Directly showing results (instead of related searches)
  • Showing search suggestions

Search Autocomplete for Magento

Search Autocomplete for Magento

Magento default quick search shows related searches as you type. From my point of view, this is not relevant at all. On the other hand, having results directly under the search box… that’s totally worth it. 

Of course, you’ll need to apply some styles to the results box.

[Off-Magento] Solving the Warning: ssh2_scp_send(): Failure creating remote file: Invalid ACK response from remote error

Recently I had to use ssh2 through php in order to send files from one server to another. I don’t know why, I was getting a error that was not actually very common on the Internet. My code was:

$connection = ssh2_connect($host, $port);
ssh2_scp_send($connection, $path_origin, $path_target, 0644);

The connection was correctly placed, but when trying to copy the file, I got:

Warning: ssh2_scp_send(): Failure creating remote file: Invalid ACK response from remote

After looking for the solution, I finally found something [not really related to this issue]. There are other ways of copying files through ssh using php, and that’s what I did. Here is the workaround I found:

<?php
$srcFile = '/path_to_origin_file';
$dstFile = '/path_to_server_file';

$host = 'ssh_host';
$port = '22';
$username = 'ssh_user';
$password = 'ssh_password';

// Create connection the the remote host
$conn = ssh2_connect($host, $port);
ssh2_auth_password($conn, $username, $password);

// Create SFTP session
$sftp = ssh2_sftp($conn);

$sftpStream = fopen('ssh2.sftp://'.$sftp.$dstFile, 'w');

try {

    if (!$sftpStream) {
        throw new Exception("Could not open remote file: $dstFile");
    }

    $data_to_send = file_get_contents($srcFile);

    if ($data_to_send === false) {
        throw new Exception("Could not open local file: $srcFile.");
    }

    if (fwrite($sftpStream, $data_to_send) === false) {
        throw new Exception("Could not send data from file: $srcFile.");
    }

    fclose($sftpStream);

} catch (Exception $e) {
    error_log('Exception: ' . $e->getMessage());
    fclose($sftpStream);
}
?>

Filter product collection by multiple categories in Magento

During the past week I’ve dealed with a very weird and stressing thing with my colleagues: filtering a product collection by multiple categories in Magento.

  • Filter by only 1 category

Magento offers a type of filter that can be used directly from the collection:

$_category = Mage::getModel('catalog/category')->load($category_id);

$collection->addCategoryFilter($_category);
  • Filter by 2 or more categories

This is a completely different story. It’s very important to proceed correctly in order to avoid errors of the type:
[blockquote]Item (Mage_Catalog_Model_Product) with the same id already exist[/blockquote]

Proceed in the following way:

1. Call your collection and filter by the attributes you want to filter (all but the category one). For example:

$collection= Mage::getResourceModel('catalog/product_collection')
           ->addFieldToFilter('is_saleable',1)
           ->addFieldToFilter('type_id', array('eq' => 'configurable'));

2. After doing this, you can apply your multiple category filter as follows:

$categories_to_filter = array('3', '4', '5');
$ctf = array();

foreach ($categories_to_filter as $k => $cat) {
     $ctf[]['finset'] = $cat;
}

$collection->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left')
            ->addAttributeToFilter('category_id',array($ctf));

Important: do it in this order if you don’t want to face weird Magento issues.

Best way of disabling the Region select for addresses in Magento

Region select is not perfect in Magento. For example, for UK, there are missing counties, probably due how official they are or maybe just because Magento didn’t take the correct database.

One way or another, region field is not considered one of the required fields for most sellers when integrating orders on their ERP.

What is the best and cleanest way for disabling this select box? From my point of view, this is the best way:

Launch this mysql query on your database:

TRUNCATE TABLE directory_country_region;
  • You don’t need code changes
  • You can easily recover this table
  • This will affect throught all the web. No more select menus for region.

If you’re not convinced, you might check other options.

Magento EE 1.13 & EE 1.8

Magento EE 1.13 is finally out (last version was released in December. The focus of this version has been performance, especially regarding indexing. These are good news, as our experience with indexing problems and performance during the last months has been really bad.

Reindex Section in Magento

Reindex Section in Magento

Magento CE 1.8 will follow soon, something completely necessary, as the last version was released in July 2012 (that means nearly 8 months without any updates, not even security updates)

The most important changes are the following ones. You can also see the complete list on the Magento Website:

  • Reindexing (Enterprise Edition only):
    • Most indexing processes now run only to update products, categories, URL redirects, and so on that have changed—eliminating the need for manual full reindexing
    • Your Magento web store is not locked at any point during reindexing
    • Reindexing is now a background process.
  • Caching (Enterprise Edition only):
    • Full page caching now invalidates only pages that are affected by product or category changes
    • Improved cache adapter for single-host systems
    • Additional option of using Redis NoSQL for cache and session storage in multi-host deployments (recommended for new deployments)
  • EE customers also get detailed performance and tuning guidelines geared toward enterprise installations
  • Sales, Value Added, and Fixed Product Tax calculations (Magento CE and EE):
  • Checkout performance (Magento CE and EE) achieved by:
    • Eliminating unnecessary calls to gift wrapping when loading the Shipping Method checkout step
    • Eliminating unnecessary RSS cache cleanups when RSS functionality is disabled
    • Eliminating unnecessary calls to the translation module when sending new order e-mails if the current locale is the same as the locale set in Magento
    • Improving the overall checkout process performance by loading the information for the current checkout step only
    • Improving the overall checkout process performance by loading the progress information for the current checkout step only