คำนำ: สิ่งนี้มีไว้เพื่อใช้เป็นทั้งการสังเกตการเขียนของสถาปัตยกรรมวีโอไอพีสำหรับชุมชน (และตัวฉันเอง) เช่นเดียวกับคำถามจริง เรากำลังทำงานร่วมกับตะกร้าสินค้าที่มีการเปลี่ยนแปลงอย่างมากและประสบการณ์การชำระเงิน แต่สาเหตุของปัญหานี้อยู่ในตรรกะหลักของ Magento
พื้นหลัง
เราได้สร้างคูปองการจัดส่งฟรีโดยใช้ฟังก์ชันราคากฎตะกร้าสินค้ามาตรฐาน มีเงื่อนไขที่ไม่มีในคูปองที่มีและการดำเนินการเพียงว่ามีการตั้งค่า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
เมื่อเปิดใช้งานการจัดส่งฟรี
ที่น่าสนใจพอไม่มีวีโอไอพีของผู้ให้บริการจัดส่งเริ่มต้นจริงพึ่งพา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
หากคุณค้นหา regex สำหรับ/row_?weight/i
(เช่นgetRowWeight
, setRowWeight
, setData('row_weight')
ฯลฯ ) ในMage_Shipping
(ผู้ให้บริการง่าย) และMage_Usa
(FedEx, 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
เพราะเราได้ปรับแต่งผู้ให้บริการ FedEx ของ Magento เพื่อคำนวณอัตราแยกต่างหากสำหรับรายการที่มาจากแหล่งกำเนิดที่แตกต่างกันแม้ว่าพวกเขาจะไปยังปลายทางเดียวกัน (และเป็นส่วนหนึ่งของที่อยู่เดียวกัน) ตัวอย่างเช่นหากคุณอาศัยอยู่ในนิวเจอร์ซีย์ราคาถูกกว่า (และเร็วกว่า) ในการจัดส่งรายการจาก NJ มากกว่าจาก CA - และหากคุณมีรายการจากทั้ง NJ และ CA ในการสั่งซื้อคุณจะเห็นต้นทุน (และโดยประมาณ) วันที่ส่งมอบ) ของการจัดส่งแต่ละครั้ง
โดยสรุปดูเหมือนว่าเราสามารถแก้ไขปัญหานี้ได้อย่างง่ายดายโดยการเพิกเฉยrow_weight
และใช้งานweight * qty
โดยตรง แต่มันนำเราไปสู่:
คำถาม
ทำไมShipping
ยอดรวมของการตั้งค่าrow_weight
ของรายการเสนอราคาถึง0
หากการจัดส่งฟรีมีผล? ดูเหมือนว่านี่จะไม่ถูกใช้งานได้ทุกที่
ข้อสังเกตเพิ่มเติม
ฉันละเลยที่จะพูดถึงว่าrow_weight
จริงอาจจะไม่ใช่ศูนย์ แต่ก็ยังน้อยกว่าweight * qty
ถ้าเป็นจำนวนที่แทนfree_shipping
true
ฉันถือว่าวัตถุประสงค์ของการนี้คือการให้วิธีแก้ปัญหากับสถานการณ์เช่นนี้:
ฉันมีสินค้าชนิดเดียวกัน 3 ชิ้นในรถเข็นสินค้าแต่ละชิ้นมีน้ำหนัก 2 ปอนด์ ฉันใช้คูปองจัดส่งฟรี แต่ จำกัด ไว้ที่ปริมาณ 2 ดังนั้นจึงใช้ได้กับ 2 รายการเท่านั้น ตอนนี้เมื่อฉันดูอัตราค่าจัดส่งฉันจะดูอัตราค่าจัดส่งเป็น 2 ปอนด์ (2 + 0 + 0) มากกว่า 6 ปอนด์ (2 + 2 + 2)
ดูเหมือนว่าจะสมเหตุสมผล แต่มีสองปัญหาที่สำคัญ:
ผู้ให้บริการวีโอไอพีที่เป็นค่าเริ่มต้นไม่ทำงานเช่นนี้ (ใช้น้ำหนักรวมที่อยู่ดูที่ด้านบน)
แม้ว่าผู้ให้บริการบางรายทำงานอย่างนี้ก็หมายความว่าฉันสามารถเลือกวิธีการจัดส่งใด ๆ (เช่นการจัดส่งข้ามคืน) และจ่ายเฉพาะค่าน้ำหนัก 1 รายการ - ความหมายผู้ขายจะต้องครอบคลุมค่าใช้จ่ายอีก 2 รายการ . มันขึ้นอยู่กับผู้ค้าว่าฉันจะจ่ายแค่ 1 ชิ้นเท่านั้นและจากนั้นจัดส่งอีก 2 รายการโดยใช้วิธีที่คุ้มค่ามากขึ้นสร้างความไม่ตรงกันระหว่างที่วีโอไอพีแสดงกับสินค้าจริง ส่งออกไปแล้ว