서문 : 이것은 커뮤니티 (및 본인)를위한 Magento의 아키텍처에 대한 서면 관찰과 실제 질문의 역할을합니다. Google은 크게 수정 된 장바구니 및 결제 환경을 사용하고 있지만이 문제의 근원은 마젠 토의 핵심 논리에 있습니다.
배경
표준 장바구니 가격 규칙 기능을 사용하여 무료 배송 쿠폰을 만들었습니다. 쿠폰에는 조건이 없으며 Free Shipping
로 설정된 유일한 동작은입니다 For matching items only
. 조건이 없으므로 모든 판매 견적 항목 free_shipping
에 1
대해 설정 됩니다 .
일반적으로 무료 배송 방법을 사용하도록 설정했습니다. Freeshipping
요청이 무료 배송 또는 소계 일치가 있거나 임계 값을 초과 할 때마다 캐리어 모델은 속도를 제공합니다 (그러나 우리는 임계 값 옵션을 사용하지 않는). 참조 Mage_Shipping_Model_Carrier_Freeshipping::collectRates
:
$this->_updateFreeMethodQuote($request);
if (($request->getFreeShipping()) // <-- This is the condition we're relying on
|| ($request->getBaseSubtotalInclTax() >=
$this->getConfigData('free_shipping_subtotal'))
) {
/* Snip: Add $0.00 method to the result */
}
그리고 이것 Mage_Shipping_Model_Carrier_Freeshipping::_updateFreeMethodQuote
처럼 보입니다 :
protected function _updateFreeMethodQuote($request)
{
$freeShipping = false;
$items = $request->getAllItems();
$c = count($items);
for ($i = 0; $i < $c; $i++) {
if ($items[$i]->getProduct() instanceof Mage_Catalog_Model_Product) {
if ($items[$i]->getFreeShipping()) {
$freeShipping = true;
} else {
return;
}
}
}
if ($freeShipping) {
$request->setFreeShipping(true);
}
}
따라서 모든 품목이 free_shipping
정확한 값으로 설정되어있는 한 (쿠폰으로 인해), 무료 배송이 가능합니다. 그리고 우리는!
문제
그러나 주요 부작용 row_weight
이 있습니다. FedEx 운송 업체의 맞춤형 버전에서와 같이 품목에 의존하는 모든 운송 방법 은 무료 배송이 활성화 row_weight
되어 0
있을 때 각 품목 이 설정되어 있기 때문에 적절한 운송 요금을 계산하지 못합니다 .
흥미롭게도 Magento의 기본 운송 업체는 실제로에 의존 row_weight
하지 않지만, 왜 / 언제 row_weight
로 설정되어 있는지 알아 낸 후에 그 정보를 얻을 수 0
있습니다.
이유 row_weight
가 무엇인지 파악0
이 부분은 실제로 파기 쉬웠습니다. 로 Mage_Sales_Model_Quote_Address_Total_Shipping::collect
설정하는 row_weight
것을 포함 하여 배송 계산의 큰 덩어리가 발생 합니다 0
.
public function collect(Mage_Sales_Model_Quote_Address $address)
{
parent::collect($address);
foreach ($items as $item) {
/* Snip: Handling virtual items and parent items */
if ($item->getHasChildren() && $item->isShipSeparately()) {
/* Snip: Handling items with children */
}
else {
if (!$item->getProduct()->isVirtual()) {
$addressQty += $item->getQty();
}
$itemWeight = $item->getWeight();
$rowWeight = $itemWeight*$item->getQty();
$addressWeight+= $rowWeight;
if ($freeAddress || $item->getFreeShipping()===true) {
$rowWeight = 0;
} elseif (is_numeric($item->getFreeShipping())) {
$freeQty = $item->getFreeShipping();
if ($item->getQty()>$freeQty) {
$rowWeight = $itemWeight*($item->getQty()-$freeQty);
}
else {
$rowWeight = 0;
}
}
$freeMethodWeight+= $rowWeight;
$item->setRowWeight($rowWeight);
}
}
이것이 Magento의 기본 이동 통신사에 영향을 미치지 않는 이유
당신이에 대한 정규식 검색 할 경우 /row_?weight/i
(예를 들어 getRowWeight
, setRowWeight
, setData('row_weight')
에서, 등) Mage_Shipping
(단순 사업자) 및 Mage_Usa
(페덱스, UPS, 그리고 몇몇 다른 사업자), 아무것도 팝업 없습니다. 왜? 기본 운송 업체는 개별 품목 무게가 아닌 총 주소 무게를 사용하기 때문입니다.
예를 들어 봅시다 Mage_Usa_Model_Shipping_Carrier_Fedex::setRequest
:
public function setRequest(Mage_Shipping_Model_Rate_Request $request)
{
$this->_request = $request;
$r = new Varien_Object();
/* Snip */
$weight = $this->getTotalNumOfBoxes($request->getPackageWeight());
$r->setWeight($weight);
if ($request->getFreeMethodWeight()!= $request->getPackageWeight()) {
$r->setFreeMethodWeight($request->getFreeMethodWeight());
}
그리고 요청은 패키지 무게를 어디서 얻습니까? 답은 다음과 Mage_Sales_Model_Quote_Address::requestShippingRates
같습니다.
public function requestShippingRates(Mage_Sales_Model_Quote_Item_Abstract $item = null)
{
/** @var $request Mage_Shipping_Model_Rate_Request */
$request = Mage::getModel('shipping/rate_request');
/* Snip */
$request->setPackageWeight($item ? $item->getRowWeight() : $this->getWeight());
특정 항목을 매개 변수로 제공하지 않고 호출되었으므로 $item->getRowWeight()
여기 에서 사용을 무시할 수 있습니다 .requestShippingRates
Mage_Sales_Model_Quote_Address_Total_Shipping::collect
public function collect(Mage_Sales_Model_Quote_Address $address)
{
parent::collect($address);
foreach ($items as $item) {
/* Snip: Handling virtual items and parent items */
if ($item->getHasChildren() && $item->isShipSeparately()) {
/* Snip: Handling items with children */
}
else {
if (!$item->getProduct()->isVirtual()) {
$addressQty += $item->getQty();
}
$itemWeight = $item->getWeight();
$rowWeight = $itemWeight*$item->getQty();
$addressWeight+= $rowWeight;
if ($freeAddress || $item->getFreeShipping()===true) {
$rowWeight = 0;
} elseif (is_numeric($item->getFreeShipping())) {
$freeQty = $item->getFreeShipping();
if ($item->getQty()>$freeQty) {
$rowWeight = $itemWeight*($item->getQty()-$freeQty);
}
else {
$rowWeight = 0;
}
}
$freeMethodWeight+= $rowWeight;
$item->setRowWeight($rowWeight);
}
}
$address->setWeight($addressWeight);
$address->setFreeMethodWeight($freeMethodWeight);
$address->collectShippingRates();
무료 배송이 적용 row_weight
되는 0
경우 각 항목 이 설정되어 있는 곳과 동일하므로 친숙해 보일 것 입니다. $addressWeight
각 항목을 합산하는 방법에 $rowWeight
유의하십시오. 그러나 이전 row_weight
에0
수행 된 작업 은로 설정되어 있습니다.
기본적으로 주소 가중치는 free_shipping
각 항목 의 값에 관계없이 항상 모든 항목의 총 가중치입니다 . Magento의 기본 이동 통신사는 주소 가중치에만 의존하기 때문에 문제 row_weight
가 표시되지 않습니다.
왜 우리는 필요합니까 row_weight
우리는 필요 row_weight
우리가 서로 다른 기원에서 오는 항목에 대해 별도의 요금을 계산하기 젠토의 페덱스 캐리어를 정의했기 때문에 그들은 같은 목적지로가는 (따라서 같은 주소의 일부) 경우에도. 예를 들어 NJ에 거주하는 경우 CA보다 NJ에서 상품을 배송하는 것이 더 저렴하고 빠릅니다. 주문에 NJ와 CA의 상품이 있으면 비용을 볼 수 있습니다. 각 발송물의 배달 날짜).
대체로 직접 무시 row_weight
하고 사용 하여이 문제를 쉽게 해결할 수있는 것처럼 보입니다 weight * qty
. 그러나 그것은 우리를 다음과 같이 이끌어줍니다.
질문
무료 배송이 적용 되는 경우 Shipping
총계 row_weight
가 판매 견적 항목 의 총계를 설정하는 이유는 무엇 0
입니까? 이것은 어디에도 활용되지 않는 것 같습니다.
추가 관찰
row_weight
실제로 0이 아닌 수는 있지만 대신 숫자 보다 작은 weight * qty
경우 free_shipping
는 언급하지 않았습니다 true
. 나는 이것의 목적이 다음과 같은 시나리오에 대한 해결책을 제공하는 것이라고 가정합니다.
장바구니에 같은 제품으로 3 개의 품목이 있으며 각 품목의 무게는 2 파운드입니다. 무료 배송 쿠폰을 적용하지만 수량이 2 개로 제한되어 있으므로 2 개 품목에만 적용됩니다. 이제 운송 요금을 살펴볼 때 6 파운드 (2 + 2 + 2)가 아닌 2 파운드 (2 + 0 + 0)의 운송 요금을 살펴 보겠습니다.
이것은 말이되는 것처럼 보이지만 두 가지 주요 문제가 있습니다.
기본 Magento 캐리어는 이와 같이 작동하지 않습니다 (주소 총 중량을 사용합니다 (위 참조)).
캐리어 중 일부는이 같은 일을하더라도, 그게 내가 선택할 수 있다는 것을 의미 어떤 배송 방법 (예를 들어 야간 배송) 및 1 개 항목의 무게 만 지불 - 의미를, 상인은 다른 두 항목의 비용을 충당 할 것 . 어떻게 든 1 품목의 무게에 대해서만 비용을 지불 한 다음 더 비용 효율적인 방법을 사용하여 다른 2 품목을 운송하여 Magento가 표시하는 것과 실제로 품목이 어떻게 다른지 불일치를 만드는 것은 판매자에게 달려 있습니다. 배송되었습니다.