ปรับเปลี่ยนอัตราภาษีในรายการราคารถเข็นและคำนวณใหม่


31

ฉันมีหมวดหมู่ของผลิตภัณฑ์ที่ (ถูกกฎหมาย) ต้องมีการเปลี่ยนแปลงอัตราภาษีของพวกเขาเมื่อคุณสั่งซื้อมากกว่าจำนวนที่แน่นอน ฉันได้ขยายแบบจำลองภาษีต่างๆเพื่อให้สามารถใช้งานได้เมื่อคุณเพิ่มผลิตภัณฑ์ใหม่ลงในรถเข็น แต่ฉันมีปัญหาเมื่อผู้ใช้อัปเดตปริมาณในรถเข็นหรือเพิ่มผลิตภัณฑ์เพิ่มเติมซึ่งทิปปริมาณที่มีอยู่ในรถเข็นเกินเกณฑ์แล้ว จำนวน

ปัญหาที่ 1:

ก่อนอื่นฉันไม่ใช่ 100% ที่จะต้องสังเกตเหตุการณ์ ฉันได้ลองแล้ว

checkout_cart_save_after(ขึ้นอยู่กับสิ่งนี้ -> https://stackoverflow.com/questions/14362702/magento-programatically-update-cart-via-event )

checkout_cart_update_items_after(ขึ้นอยู่กับสิ่งนี้ -> https://stackoverflow.com/questions/5104482/programmatically-add-product-to-cart-with-price-change )

sales_quote_save_before(ขึ้นอยู่กับสิ่งนี้ -> https://stackoverflow.com/questions/7638858/magento-recalculate-cart-total-in-observer )

ปัญหาที่ 2:

ฉันสามารถเข้าถึงรายการอ้างอิงจากรถเข็นมีหลายวิธีที่ดูเหมือนว่า ฉันยังสามารถวนซ้ำแต่ละรายการในรถเข็นอัปเดตคุณสมบัติของรายการเหล่านั้นแล้วบันทึกรายการ (อย่างน้อยก็ชั่วคราว) อย่างไรก็ตามฉันไม่สามารถบันทึกใบเสนอราคาและคำนวณภาษีใหม่ในเช็คเอาต์ได้

เหตุผลส่วนหนึ่งคือในขณะที่ฉันสามารถเข้าถึงใบเสนอราคารถเข็นได้ฉันไม่แน่ใจว่าวิธีการใดที่จะใช้เพื่อให้สามารถเขียนลงไปได้

สิ่งที่ฉันได้ลอง:

สิ่งที่ฉันได้ลองในแง่ของการเข้าถึงเนื้อหาของรถเข็นนั้นขึ้นอยู่กับเหตุการณ์ที่ฉันสังเกตเห็น แต่ฉันได้ลองทั้งหมดต่อไปนี้แล้ว

1. 
$item = $observer->getQuoteItem;

2.
$cart = Mage::getSingleton('checkout/cart');
$cartItems = $cart->getCart()->getItems(); 

3.
$cart = $observer->getData('cart');
$quote = $cart->getData('quote');
$cartItems = $quote->getAllVisibleItems();

4.
$cartHelper = Mage::helper('checkout/cart');
$cartItems = $cartHelper->getCart()->getItems(); 

5.
$quote = Mage::getModel('checkout/cart');
$cartItems = $quote->getItems(); 

อย่างน้อยก็ดูเหมือนว่าจะช่วยให้ฉันสามารถเข้าถึงคำพูดวิ่งผ่านพวกเขาและอัปเดตรายการได้

6.
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();

สิ่งนี้ทำให้ฉันสามารถอัปเดตรายการอ้างอิงแต่ละรายการได้เมื่อฉันวนซ้ำ (ฉันเชื่อว่าใช้เวทเซเตอร์เพราะฉันไม่สามารถหาวิธีการที่สอดคล้องกันได้) ฉันหวังว่าจะสามารถอัปเดตรหัสระดับภาษีสำหรับรายการใบเสนอราคาจากนั้นคำนวณภาษีใหม่ ถ้าฉันใช้สิ่งต่อไปนี้ (โดยที่ $ taxClassId แตกต่างจากที่ใช้โดยแต่ละรายการที่อ้างถึง);

$item->setTaxClassId( $taxClassId );
$item->getProduct()->setIsSuperMode(true);
$item->save;

จากนั้นบันทึกผลลัพธ์

Mage::log($item->debug(), null,'taxobserver.log', true);

แสดงให้เห็นว่าฉันได้อัพเดทรายการใบเสนอราคานี้และเปลี่ยนรหัสภาษีแล้ว อย่างไรก็ตามถ้าฉันทำตามและพยายามบันทึกใบเสนอราคาที่แก้ไขแล้ว;

$quote->setTotalsCollectedFlag(false)->collectTotals();
$quote->save();     

จากนั้นทำการดีบักอีกครั้ง

Mage::log($item->debug(), null,'taxobserver.log', true);

การเปลี่ยนแปลงของฉันยังไม่ได้รับการบันทึกการเปลี่ยนแปลงรายการอ้างถูกรีเซ็ตและยอดรวมของรถเข็นจะไม่คำนวณใหม่ เริ่มสงสัยว่าการหาตึกสูงเพื่อกระโดดออกอาจเป็นทางออกสำหรับตึกนี้หรือไม่


ได้โปรดใครช่วยฉันออกไปแก้ปัญหานี้: stackoverflow.com/questions/27978781/… ขอบคุณ
satish

คำตอบ:


35

ข้อเสนอแนะของฉันคือการวางผู้สังเกตการณ์ในsales_quote_collect_totals_beforeเหตุการณ์ที่เกิดขึ้นในMage_Sales_Model_Quote::collectTotalsวิธีการก่อนที่จะเริ่มกระบวนการรวบรวมทั้งหมด จากนั้นจากภายในวิธีผู้สังเกตการณ์นี้ให้วนรายการใบเสนอราคาและเปลี่ยนคลาสภาษีในออบเจคผลิตภัณฑ์ (โหลดแล้ว) ที่คุณสามารถเรียกคืนได้จากรายการใบเสนอราคา

หลังจากที่คุณตั้งค่าข้อมูลบนวัตถุผลิตภัณฑ์สิ่งที่คุณทำอย่าพยายามและบันทึกลงในฐานข้อมูล การกำหนดระดับภาษีตามที่ต้องการบนวัตถุผลิตภัณฑ์ในหน่วยความจำจะดีพอที่จะมีตรรกะผลรวมการรวบรวมที่พบในการMage_Tax_Model_Sales_Total_Quote_Taxเบิกสินค้าซึ่งระดับภาษีที่ควรจะขึ้นอยู่กับการคำนวณของ การบันทึกผลิตภัณฑ์ (ตามที่คุณพยายามทำในตัวอย่างโค้ดของคุณด้านบน) จะทำให้เกิดปัญหาด้านประสิทธิภาพที่สำคัญสร้างเงื่อนไขการแข่งขันในกระบวนการคำนวณและไม่ใช่วิธีปฏิบัติที่ดี

เหตุผลที่กิจกรรมที่คุณพยายามทำงานด้วยนั้นไม่ได้ช่วยให้คุณสามารถทำสิ่งที่คุณต้องการให้สำเร็จได้เพราะสิ่งเหล่านั้นเกิดขึ้นหลังจากการคำนวณทั้งหมดซึ่งเป็นกระบวนการที่จะดำเนินการเพียงครั้งเดียวก่อนที่จะบันทึกใบเสนอราคา

สิ่งที่ควรรู้เกี่ยวกับกระบวนการรวมทั้งหมดคือเมื่อเรียกใช้แล้วโดยไม่ต้องทำงานพิเศษคุณไม่สามารถเรียกมันอีกครั้งเพื่อคำนวณใหม่อีกครั้งโดยอิงจากการเปลี่ยนแปลงที่คุณทำกับรายการอ้างอิง ดู tie-bit นี้ที่ฉันนำมาจากชุดบล็อกซึ่งเป็นเพื่อนร่วมงานของฉันที่เพิ่งรวมตัวกันในกระบวนการรวบรวมทั้งหมด:

ตอนนี้คุณเข้าใจว่าเกิดอะไรขึ้นในระหว่างกระบวนการรวบรวมผลรวมคุณอาจพบว่าสะดวกหรือจำเป็นที่จะต้องเรียกมันว่าตัวคุณเองโดยตรง ก่อนที่คุณจะเริ่มรู้สึกมั่นใจเกินไปกับการใช้ collectTotals เพื่อจุดประสงค์ของคุณเองโปรดคำนึงถึงกฎต่อไปนี้:

ไม่สามารถเพิ่มผลิตภัณฑ์ลงในเครื่องหมายคำพูดหลังจากที่เรียกใช้ collectTotals!

. . . นอกเสียจากว่าแคชรายการที่อยู่อ้างถึงถูกล้าง

เกือบทุกวิธี "รวบรวม" ของแบบจำลองทั้งหมดอาศัยการดึงรายการอ้างอิงจากที่อยู่และวนลูปผ่านพวกเขา ครั้งแรกที่ getAllItems ทำงานบนที่อยู่ใบเสนอราคาการรวบรวมรายการจะถูกแคชด้วยคีย์เฉพาะและเป็นคอลเลกชันแคชที่ส่งคืนเมื่อมีการโทรตามมา

หากคุณมีปัญหาเกี่ยวกับการดำน้ำลึกเข้าไปในกระบวนการรวบรวมผลรวมคุณสามารถตรวจสอบซีรี่ส์สี่ภาคแรกในคอลเลกชันทั้งหมดที่นี่เพื่ออ่านเชิงลึกเพิ่มเติมได้ที่: การรวบรวมของสะสมของวีโอไอพี: บทนำ

ในการสรุปคุณจะต้องติดตามเหตุการณ์ที่เรียกใช้ก่อนที่กระบวนการรวบรวมผลรวม (และก่อนที่จะได้รับ getAllItems บนที่อยู่อัญประกาศ) เพื่อให้การเปลี่ยนแปลงที่คุณทำกับรายการจะถูกใช้โดยนักสะสมทั้งหมด ฉันไม่ได้ตรวจสอบว่าsales_quote_collect_totals_beforeเหตุการณ์ที่แนะนำทำงานก่อนที่จะมีการเรียกไปยังที่getAllItemsอยู่ในใบเสนอราคา แต่ฉันเกือบจะแน่ใจว่ามันจะทำงานในสิ่งที่คุณต้องการ แต่ถ้าไม่หวังว่าฉันจะให้บริบทเพียงพอสำหรับคุณที่จะคิดว่าเหตุการณ์ที่คุณต้องจับเพื่อให้มันทำงานได้


คำตอบนี้ดีเกินกว่าที่ฉันคาดหวังไว้ ยอดเยี่ยมขอบคุณที่สละเวลา คำตอบที่ยอดเยี่ยม
McNab

โอ๊ะ! หลังจากใช้เวลาทั้งวันไปกับการทำสิ่งนี้และไม่ให้มันทำงาน II ในที่สุดก็รู้ว่ามันเป็นโมเดลที่เขียนซ้ำไม่ดีที่อื่นในโมดูล มันทำงานได้อย่างสมบูรณ์และฉันได้เรียนรู้มากมายจากมันขอบคุณอีกครั้งเดวิด
McNab

@McNab ดีใจที่ได้ยินว่าคุณทำงานได้ หนึ่งในพื้นที่ที่ซับซ้อนของวีโอไอพีอย่างแน่นอน :)
davidalger

+1 บนบล็อกที่ลิงก์ ฉันมองข้ามมันสองสามครั้งแรกที่ฉันอ่าน มันเป็นความช่วยเหลือที่ยิ่งใหญ่
pspahn

6

มีเหตุการณ์อื่น: sales_quote_item_set_productใน Mage_Sales_Model_Quote_Item :: setProduct

Mage::dispatchEvent('sales_quote_item_set_product', array(
            'product' => $product,
            'quote_item'=>$this
        ));

คุณสามารถแก้ไขคลาสภาษีผลิตภัณฑ์โดยใช้กิจกรรมนี้ ใช้วิธีอ้างถึง getQty เพื่อค้นหาจำนวนที่เพิ่มลงในรถเข็น


ขอบคุณสำหรับสิ่งนี้มันมีประโยชน์ที่จะรู้ - ฉันรู้จากคำตอบของ @ davidalger ว่าฉันไม่ควรปรับเปลี่ยนระดับภาษีของผลิตภัณฑ์ในตอนนี้ แต่เป็นรุ่นอ้างอิง ดีที่จะรู้ว่า
McNab

คุณสามารถปรับเปลี่ยนคลาสภาษีของใบเสนอราคาได้จริงคุณยังสามารถเข้าถึงในเหตุการณ์กับวัตถุ quoteItem ได้
PandaWebStudio

อ่าตกลง - ฉันเข้าใจผิด ขอบคุณสำหรับคำชี้แจง :)
McNab

@PandaWebStudio วิธีการกำหนดจำนวนภาษีที่กำหนดเองสำหรับรายการอ้าง? นี่คือคำถามของฉันmagento.stackexchange.com/questions/274520/…
jafar pinjar

2

บางทีการพยายามเปลี่ยนคลาสแท็กซี่อาจไม่ใช่วิธีที่ดีที่สุด ทำไมไม่สร้างผลิตภัณฑ์ที่คล้ายกันสำหรับผลิตภัณฑ์เหล่านั้นที่ใช้ระดับภาษีที่สูงขึ้นและตั้งค่าจำนวนน้อยที่สุดในตะกร้าสำหรับผลิตภัณฑ์นั้น จากนั้นใช้ปุ่มcheckout_cart_update_items_afterเพื่อสลับผลิตภัณฑ์ตามปริมาณรวมในรถเข็น?

นี่ไม่ใช่ 'แนวปฏิบัติที่ดีที่สุด' แต่มันอาจช่วยให้คุณคิดไปอีกทางหนึ่งได้

หรือลองตั้งค่าบางอย่างด้วยhttp://www.mageworx.com/multi-fees-magento-extension.htmlที่คุณเพิ่ม 'ค่าธรรมเนียม' สำหรับภาษีเพิ่มเติม นี่อาจเป็นวิธีที่ดีกว่าในการทำ แต่จะไม่ปรากฏในยอดรวมภาษีเพิ่มเติมเป็นบรรทัดรวมของคำสั่งซื้อพิเศษ


ขอบคุณสำหรับการตอบกลับของซานเดอร์ มันเป็นความคิดที่ดีและฉันก็ไม่ได้คิด ฉันจะบอกคุณว่าทำไมฉันจึงไม่นึกว่า - ผลิตภัณฑ์พื้นฐานกำลังทำงานอยู่แม้ว่าชุด uMarketplace ของ Unirgy และเป็นงานที่ต้องประหลาดใจมากที่ได้รับมันไปยังที่ที่มันทำงานเหมือนเว็บไซต์เปรียบเทียบราคา ฉันคิดว่านั่นอาจเป็นงานที่ยิ่งใหญ่ หากฉันไม่ได้รับการอัพเดทรายการอ้างอิงนี้ฉันจะต้องดูมัน
McNab

ประณามฉันไม่สามารถเอาชนะคำตอบของคุณได้ในขณะที่ฉันใช้เงินทั้งหมดไปกับค่าหัวนี้! +1 :) จะอัปโหลดเมื่อฉันได้รับมากขึ้น
McNab

ฮ่าฮ่าไม่มีปัญหาฉันเข้าใจปัญหาและนี่จะไม่เป็นทางออกที่ดีสำหรับกรณีนี้ ฉันอาจจะไปกับผู้ติดตามหลายคนนั่นเป็นวิธีที่ 'สะอาดกว่า'
Sander Mangel

FWIW ฉันจะไม่แนะนำเส้นทางนี้…ถ้าเพียงเพราะจะทำให้การบัญชีสำหรับการขายและการติดตามสินค้าคงคลังเป็นฝันร้ายที่อาจเกิดขึ้น อย่างที่ OP บอกไว้ไม่ใช่แนวปฏิบัติที่ดีที่สุด แต่ฉันจะเพิ่ม: มันจะทำให้เกิดปัญหามากกว่าที่จะแก้
davidalger

0

ใช้สิ่งนี้ <sales_quote_collect_totals_before>

และในการทำงานของคุณทำเช่นนั้น

 public function quoteCollectTotalsBefore(Varien_Event_Observer $observer)
    $quote = $observer->getQuote();
    foreach ($quote->getAllItems() as $item)
    {
        $product = $item->getProduct();
        $product->setTaxClassId($product_tax_class_id);
    }
 }

ฉันหวังว่ามันจะทำงานได้อย่างแน่นอน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.