YAMB: Creditmemo with shippingInclTax > 0 and shippingAmount = 0

I think I just found yet another Magento Bug (YAMB).

I'm working on credit memos and want to add tax to adjustments (I hope I'll write a blog post about this soon - please remind me if you are interested).

I had the problem, that in \Mage_Sales_Model_Order_Creditmemo_Total_Shipping::collect the shippingAmount was 0 (as expected) but the shippingIncludingTax is the complete shipping amount (and is printed on our credit memos).

The problem ends here right before the end of the method.

$creditmemo->setShippingAmount($shipping);
$creditmemo->setBaseShippingAmount($baseShipping);
$creditmemo->setShippingInclTax($shippingInclTax);
$creditmemo->setBaseShippingInclTax($baseShippingInclTax);

I think the bug is the following problem. In the beginning all shipping values are initialized with the values from the order:

$shipping               = $order->getShippingAmount();
$baseShipping           = $order->getBaseShippingAmount();
$shippingInclTax        = $order->getShippingInclTax();
$baseShippingInclTax    = $order->getBaseShippingInclTax();

Due to the fact, that we do it through the backend, the following comment helps us. In the beginning I ignored the comment, and assumed that the baseShippingAmount is 0 and therefore the if shouldn't be entered.

$isShippingInclTax = Mage::getSingleton('tax/config')->displaySalesShippingInclTax($order->getStoreId());

/**
 * Check if shipping amount was specified (from invoice or another source).
 * Using has magic method to allow setting 0 as shipping amount.
 */
if ($creditmemo->hasBaseShippingAmount()) {
    $baseShippingAmount = Mage::app()->getStore()->roundPrice($creditmemo->getBaseShippingAmount());
    if ($isShippingInclTax && $baseShippingInclTax != 0) {
        $part = $baseShippingAmount/$baseShippingInclTax;
        $shippingInclTax    = Mage::app()->getStore()->roundPrice($shippingInclTax*$part);
        $baseShippingInclTax= $baseShippingAmount;
        $baseShippingAmount = Mage::app()->getStore()->roundPrice($baseShipping*$part);
    }

What happens here? We get the current setting for displaySalesShippingInclTax, which should be including tax (but was excluding tax in my case).

So, if the tax setting is "wrong" (excluding tax), we don't enter the if block.

If we enter it, the part of the shipping would be calculated which is refunded (0) and everything is updated. But when the if block is not entered, the shippingInclTax is not updated and therefore the value of shippingInclTax is not consistent with shippingAmount

Images is from Pixabay and CC0
Thanks to 777546-777546

Tab is rendered in left block instead of content

I want to add tabs to a custom form in the backend.

There are a couple of great tutorials how to add tabs, like from Inchoo or Erfan Imani.

But I wanted this:

And got this:

The problem is simple - if you know it (costs me an hour and a few hairs):

The tabs are rendered with JS. So they live originally in left, but they are shown in content, to be more specific in the node, defined by:

class My_Module_Block_Adminhtml_Project_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs {

    public function __construct()
    { 
        // ...
        $this->setDestElementId('project_form');
    }
}

And this id needs to be the same as in

class My_Module_Block_Adminhtml_Project_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _prepareForm()
    {
        $form = new Varien_Data_Form(
            [
                'id'     => 'project_form',
            ]);
    }
}

Hope this helps anyone.

Add Amin User

Magento Cheat Sheet, how to add a magento admin user, directly thorugh SQL

Thanks to Atwix, i found the SQL which is needed to create a magento admin user.

Cheat sheet for me:

SET @fistname = 'Fabian';
SET @lastname = 'Blechschmidt';
SET @email = 'mailaddress@example.com';
SET @username = 'fabian';
SET @password = 'password';
SET @salt = 'Fl';

INSERT INTO admin_user
SELECT
NULL user_id,
@fistname firstname,
@lastname lastname,
@email email,
@username username,
CONCAT(MD5(CONCAT(@salt, @password)), ':', @salt) password,
NOW( ) created,
NULL modified,
NULL logdate,
0 lognum,
0 reload_acl_flag,
1 is_active,
(SELECT MAX(extra) FROM admin_user WHERE extra IS NOT NULL) extra,
NULL rp_token,
NOW() rp_token_created_at;

INSERT INTO admin_role
SELECT
NULL role_id,
(SELECT role_id FROM admin_role WHERE role_name = 'Administrators') parent_id,
2 tree_level,
0 sort_order,
'U' role_type,
(SELECT user_id FROM admin_user WHERE username = @username) user_id,
@username role_name

You have imported the sample data (which are based on EE)? Use this:

SET @fistname = 'Fabian';  
SET @lastname = 'Blechschmidt';  
SET @email = 'mailaddress@example.com';  
SET @username = 'fabian';  
SET @password = 'password';  
SET @salt = 'Fl';


INSERT INTO admin_user  
SELECT  
NULL user_id,  
@fistname firstname,
@lastname lastname,
@email email,
@username username,
CONCAT(MD5(CONCAT(@salt, @password)), ':', @salt) password,  
NOW( ) created,  
NULL modified,  
NULL logdate,  
0 lognum,  
0 reload_acl_flag,  
1 is_active,  
(SELECT MAX(extra) FROM admin_user WHERE extra IS NOT NULL) extra,
NULL rp_token,  
NOW() rp_token_created_at,  
NULL failures_num,  
NULL first_failure,  
NULL lock_expires;

INSERT INTO admin_role  
SELECT  
NULL role_id,  
(SELECT role_id FROM admin_role WHERE role_name = 'Administrators') parent_id,
2 tree_level,  
0 sort_order,  
'U' role_type,  
(SELECT user_id FROM admin_user WHERE username = @username) user_id,
@username role_name,
1 gws_is_all,  
1 gws_websites,  
1 gws_store_groups;  

Multiselect Bug in the backend

In Magento version < 1.7.0.0-alpha1 it is not possible to empty a multiselect.

In the adminbackend in Magento is a bug, which prevents a multiselect to become empty.

<select>

A <select> element is not submited, if no option is selected. To submit a value you need to render a <input type="hidden" /> element before it. This way, the variable is set in $_GET or $_POST and may be overwritten by the <select>.

Bug in magento

This <input type="hidden" /> is not rendered before Version 1.7.0.0-alpha1.

Fix

Thanks to this thread I found a quick, good fix (as magento fixed it in versions > 1.7.0.0-alpha1):

// app/code/core/Mage/Adminhtml/Block/Widget/Form.php:203
} else if ($inputType == 'multiselect') {
    $element->setValues($attribute->getSource()->getAllOptions(false, true));
    $element->setCanBeEmpty(true); // add this line

The line number is from version 1.7.0.2