Figured I'd take a stab at this... ;)
Quite an interesting question you've posed here so here's why I think they did it, however I'm still working to track down when this particular case comes into play.
Going over the USPS carrier method, it looks like International Requests to their API provide itemized weights for each product. This is the only carrier that I can find that does this. Find the full method below, and the highlighted section below that.
protected function _formIntlShipmentRequest(Varien_Object $request)
{
$packageParams = $request->getPackageParams();
$height = $packageParams->getHeight();
$width = $packageParams->getWidth();
$length = $packageParams->getLength();
$girth = $packageParams->getGirth();
$packageWeight = $request->getPackageWeight();
if ($packageParams->getWeightUnits() != Zend_Measure_Weight::POUND) {
$packageWeight = Mage::helper('usa')->convertMeasureWeight(
$request->getPackageWeight(),
$packageParams->getWeightUnits(),
Zend_Measure_Weight::POUND
);
}
if ($packageParams->getDimensionUnits() != Zend_Measure_Length::INCH) {
$length = round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getLength(),
$packageParams->getDimensionUnits(),
Zend_Measure_Length::INCH
));
$width = round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getWidth(),
$packageParams->getDimensionUnits(),
Zend_Measure_Length::INCH
));
$height = round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getHeight(),
$packageParams->getDimensionUnits(),
Zend_Measure_Length::INCH
));
}
if ($packageParams->getGirthDimensionUnits() != Zend_Measure_Length::INCH) {
$girth = round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getGirth(),
$packageParams->getGirthDimensionUnits(),
Zend_Measure_Length::INCH
));
}
$container = $request->getPackagingType();
switch ($container) {
case 'VARIABLE':
$container = 'VARIABLE';
break;
case 'FLAT RATE ENVELOPE':
$container = 'FLATRATEENV';
break;
case 'FLAT RATE BOX':
$container = 'FLATRATEBOX';
break;
case 'RECTANGULAR':
$container = 'RECTANGULAR';
break;
case 'NONRECTANGULAR':
$container = 'NONRECTANGULAR';
break;
default:
$container = 'VARIABLE';
}
$shippingMethod = $request->getShippingMethod();
list($fromZip5, $fromZip4) = $this->_parseZip($request->getShipperAddressPostalCode());
// the wrap node needs for remove xml declaration above
$xmlWrap = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><wrap/>');
$method = '';
$service = $this->getCode('service_to_code', $shippingMethod);
if ($service == 'Priority') {
$method = 'Priority';
$rootNode = 'PriorityMailIntlRequest';
$xml = $xmlWrap->addChild($rootNode);
} else if ($service == 'First Class') {
$method = 'FirstClass';
$rootNode = 'FirstClassMailIntlRequest';
$xml = $xmlWrap->addChild($rootNode);
} else {
$method = 'Express';
$rootNode = 'ExpressMailIntlRequest';
$xml = $xmlWrap->addChild($rootNode);
}
$xml->addAttribute('USERID', $this->getConfigData('userid'));
$xml->addAttribute('PASSWORD', $this->getConfigData('password'));
$xml->addChild('Option');
$xml->addChild('Revision', self::DEFAULT_REVISION);
$xml->addChild('ImageParameters');
$xml->addChild('FromFirstName', $request->getShipperContactPersonFirstName());
$xml->addChild('FromLastName', $request->getShipperContactPersonLastName());
$xml->addChild('FromFirm', $request->getShipperContactCompanyName());
$xml->addChild('FromAddress1', $request->getShipperAddressStreet2());
$xml->addChild('FromAddress2', $request->getShipperAddressStreet1());
$xml->addChild('FromCity', $request->getShipperAddressCity());
$xml->addChild('FromState', $request->getShipperAddressStateOrProvinceCode());
$xml->addChild('FromZip5', $fromZip5);
$xml->addChild('FromZip4', $fromZip4);
$xml->addChild('FromPhone', $request->getShipperContactPhoneNumber());
if ($method != 'FirstClass') {
if ($request->getReferenceData()) {
$referenceData = $request->getReferenceData() . ' P' . $request->getPackageId();
} else {
$referenceData = $request->getOrderShipment()->getOrder()->getIncrementId()
. ' P'
. $request->getPackageId();
}
$xml->addChild('FromCustomsReference', 'Order #' . $referenceData);
}
$xml->addChild('ToFirstName', $request->getRecipientContactPersonFirstName());
$xml->addChild('ToLastName', $request->getRecipientContactPersonLastName());
$xml->addChild('ToFirm', $request->getRecipientContactCompanyName());
$xml->addChild('ToAddress1', $request->getRecipientAddressStreet1());
$xml->addChild('ToAddress2', $request->getRecipientAddressStreet2());
$xml->addChild('ToCity', $request->getRecipientAddressCity());
$xml->addChild('ToProvince', $request->getRecipientAddressStateOrProvinceCode());
$xml->addChild('ToCountry', $this->_getCountryName($request->getRecipientAddressCountryCode()));
$xml->addChild('ToPostalCode', $request->getRecipientAddressPostalCode());
$xml->addChild('ToPOBoxFlag', 'N');
$xml->addChild('ToPhone', $request->getRecipientContactPhoneNumber());
$xml->addChild('ToFax');
$xml->addChild('ToEmail');
if ($method != 'FirstClass') {
$xml->addChild('NonDeliveryOption', 'Return');
}
if ($method == 'FirstClass') {
if (stripos($shippingMethod, 'Letter') !== false) {
$xml->addChild('FirstClassMailType', 'LETTER');
} else if (stripos($shippingMethod, 'Flat') !== false) {
$xml->addChild('FirstClassMailType', 'FLAT');
} else{
$xml->addChild('FirstClassMailType', 'PARCEL');
}
}
if ($method != 'FirstClass') {
$xml->addChild('Container', $container);
}
$shippingContents = $xml->addChild('ShippingContents');
$packageItems = $request->getPackageItems();
// get countries of manufacture
$countriesOfManufacture = array();
$productIds = array();
foreach ($packageItems as $itemShipment) {
$item = new Varien_Object();
$item->setData($itemShipment);
$productIds[]= $item->getProductId();
}
$productCollection = Mage::getResourceModel('catalog/product_collection')
->addStoreFilter($request->getStoreId())
->addFieldToFilter('entity_id', array('in' => $productIds))
->addAttributeToSelect('country_of_manufacture');
foreach ($productCollection as $product) {
$countriesOfManufacture[$product->getId()] = $product->getCountryOfManufacture();
}
$packagePoundsWeight = $packageOuncesWeight = 0;
// for ItemDetail
foreach ($packageItems as $itemShipment) {
$item = new Varien_Object();
$item->setData($itemShipment);
$itemWeight = $item->getWeight() * $item->getQty();
if ($packageParams->getWeightUnits() != Zend_Measure_Weight::POUND) {
$itemWeight = Mage::helper('usa')->convertMeasureWeight(
$itemWeight,
$packageParams->getWeightUnits(),
Zend_Measure_Weight::POUND
);
}
if (!empty($countriesOfManufacture[$item->getProductId()])) {
$countryOfManufacture = $this->_getCountryName(
$countriesOfManufacture[$item->getProductId()]
);
} else {
$countryOfManufacture = '';
}
$itemDetail = $shippingContents->addChild('ItemDetail');
$itemDetail->addChild('Description', $item->getName());
$ceiledQty = ceil($item->getQty());
if ($ceiledQty < 1) {
$ceiledQty = 1;
}
$individualItemWeight = $itemWeight / $ceiledQty;
$itemDetail->addChild('Quantity', $ceiledQty);
$itemDetail->addChild('Value', $item->getCustomsValue() * $item->getQty());
list($individualPoundsWeight, $individualOuncesWeight) = $this->_convertPoundOunces($individualItemWeight);
$itemDetail->addChild('NetPounds', $individualPoundsWeight);
$itemDetail->addChild('NetOunces', $individualOuncesWeight);
$itemDetail->addChild('HSTariffNumber', 0);
$itemDetail->addChild('CountryOfOrigin', $countryOfManufacture);
list($itemPoundsWeight, $itemOuncesWeight) = $this->_convertPoundOunces($itemWeight);
$packagePoundsWeight += $itemPoundsWeight;
$packageOuncesWeight += $itemOuncesWeight;
}
$additionalPackagePoundsWeight = floor($packageOuncesWeight / self::OUNCES_POUND);
$packagePoundsWeight += $additionalPackagePoundsWeight;
$packageOuncesWeight -= $additionalPackagePoundsWeight * self::OUNCES_POUND;
if ($packagePoundsWeight + $packageOuncesWeight / self::OUNCES_POUND < $packageWeight) {
list($packagePoundsWeight, $packageOuncesWeight) = $this->_convertPoundOunces($packageWeight);
}
$xml->addChild('GrossPounds', $packagePoundsWeight);
$xml->addChild('GrossOunces', $packageOuncesWeight);
if ($packageParams->getContentType() == 'OTHER' && $packageParams->getContentTypeOther() != null) {
$xml->addChild('ContentType', $packageParams->getContentType());
$xml->addChild('ContentTypeOther ', $packageParams->getContentTypeOther());
} else {
$xml->addChild('ContentType', $packageParams->getContentType());
}
$xml->addChild('Agreement', 'y');
$xml->addChild('ImageType', 'PDF');
$xml->addChild('ImageLayout', 'ALLINONEFILE');
if ($method == 'FirstClass') {
$xml->addChild('Container', $container);
}
// set size
if ($packageParams->getSize()) {
$xml->addChild('Size', $packageParams->getSize());
}
// set dimensions
$xml->addChild('Length', $length);
$xml->addChild('Width', $width);
$xml->addChild('Height', $height);
if ($girth) {
$xml->addChild('Girth', $girth);
}
$xml = $xmlWrap->{$rootNode}->asXML();
return $xml;
}
Particular section:
$packagePoundsWeight = $packageOuncesWeight = 0;
// for ItemDetail
foreach ($packageItems as $itemShipment) {
$item = new Varien_Object();
$item->setData($itemShipment);
$itemWeight = $item->getWeight() * $item->getQty();
if ($packageParams->getWeightUnits() != Zend_Measure_Weight::POUND) {
$itemWeight = Mage::helper('usa')->convertMeasureWeight(
$itemWeight,
$packageParams->getWeightUnits(),
Zend_Measure_Weight::POUND
);
}
if (!empty($countriesOfManufacture[$item->getProductId()])) {
$countryOfManufacture = $this->_getCountryName(
$countriesOfManufacture[$item->getProductId()]
);
} else {
$countryOfManufacture = '';
}
$itemDetail = $shippingContents->addChild('ItemDetail');
$itemDetail->addChild('Description', $item->getName());
$ceiledQty = ceil($item->getQty());
if ($ceiledQty < 1) {
$ceiledQty = 1;
}
$individualItemWeight = $itemWeight / $ceiledQty;
$itemDetail->addChild('Quantity', $ceiledQty);
$itemDetail->addChild('Value', $item->getCustomsValue() * $item->getQty());
list($individualPoundsWeight, $individualOuncesWeight) = $this->_convertPoundOunces($individualItemWeight);
$itemDetail->addChild('NetPounds', $individualPoundsWeight);
$itemDetail->addChild('NetOunces', $individualOuncesWeight);
$itemDetail->addChild('HSTariffNumber', 0);
$itemDetail->addChild('CountryOfOrigin', $countryOfManufacture);
list($itemPoundsWeight, $itemOuncesWeight) = $this->_convertPoundOunces($itemWeight);
$packagePoundsWeight += $itemPoundsWeight;
$packageOuncesWeight += $itemOuncesWeight;
}
To me, it appears Magento is recalculating the package weight based on the actual item weights, and not leveraging the address weight. I wonder if the package items being passed do not have their weight zeroed, because that would lead to false item weights considering the rates response would be based on bad weight data.
Shot in the dark though.
Best Answer
So here is how I did it.
First, I have used more appropriate event for that purpose, that is
sales_quote_collect_totals_before
. And second, I needed to comment out (in local copy of course), one line in Mage_SalesRule_Model_Quote_Freeshipping:That is it. The following now works well:
It works well in single shipping mode. Multishipping is probably going to need some adjustments.