カート見積品目の税率を変更し、再計算します


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();

これにより、繰り返し処理するときに各引用項目を更新できます(対応するメソッドが見つからないため、マジックセッターを使用していると思います)。見積品目の税クラスIDを更新し、税を再計算できるようにしたいと思っていました。次を使用する場合($ 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/… ありがとう。
サティッシュ

回答:


35

私の提案は、で発生するsales_quote_collect_totals_beforeイベントにオブザーバーを配置することですMage_Sales_Model_Quote::collectTotals、全体の収集プロセスを開始する前にメソッドことです。次に、このオブザーバーメソッド内から、見積品目を繰り返し、見積品目から取得できる(ロード済みの)製品オブジェクトの税クラスを変更します。

製品オブジェクトに情報を設定した後は、何をするにしても、データベースに保存しないでください。メモリー内の製品オブジェクトに必要に応じて税クラスを設定すると、Mage_Tax_Model_Sales_Total_Quote_Taxピックアップで見つかった合計集計ロジックが計算の基礎となる税クラスになるのに十分です。製品を保存すると(上記のコードサンプルで実行しようとしているように)、大きなパフォーマンスの問題が発生し、計算プロセスで競合状態が発生します。

処理しようとしているイベントが、達成しようとしていることを達成できないのは、すべての計算が見積もりの​​保存前に一度だけ実行されるプロセスであるためです。

合計収集プロセスについて指摘する価値があるのは、一度実行すると、余分な作業を行うことなく、再度呼び出して見積品目に加えた変更に基づいて再計算することはできないということです。ブログのシリーズから、最近の合計収集プロセスで私のコラージュをまとめたこのタイビットをご覧ください。

合計収集プロセス中に何が起こるかを理解したので、自分で直接呼び出すのが便利または必要であることがわかるかもしれません。ただし、独自の目的でcollectTotalsを使用することに自信を持ち始める前に、次のルールに留意してください。

collectTotalsの実行後、製品を見積に追加できません!

。。。見積住所のアイテムキャッシュがクリアされない限り。

ほぼすべての合計モデルの「収集」メソッドは、住所から見積品目を取得し、それらをループ処理することに依存しています。getAllItemsが最初に見積もりアドレスで実行されると、アイテムコレクションは実際に一意のキーでキャッシュされ、以降の呼び出しで返されるのはこのキャッシュされたコレクションです。

総計収集プロセスの仕組みの深さを実際に掘り下げてみようと思う場合は、総計収集に関する4つのパートのシリーズの最初の記事をご覧ください。 の記事をご覧ください。 MagentoのcollectTotalsを解いてください:

要約すると、合計収集プロセスの前(および引用アドレスでgetAllItemsが呼び出される前)に実行されるイベントをキャッチして、アイテムに加えた変更が合計コレクターによって使用されるようにする必要があります。提案されたsales_quote_collect_totals_beforeイベントがgetAllItems見積もりアドレスへの呼び出しの前に実行されることを確認していませんが、あなたが必要とするものに対して機能することはほぼ確実です。しかし、そうでない場合、うまくいくためにはどのイベントをキャッチする必要があるかを把握するのに十分なコンテキストを提供したことを願っています。


この答えは、私が望んでいたものをはるかに超えています。素晴らしい、時間を割いてくれてありがとう。素晴らしい答え。
マクナブ

ああ!これに終日を費やし、それが機能しないようになった後、IIは最終的に、モジュールの他の場所でひどく書き直されたモデルになっていることに気付きました。これは完璧に機能し、私はそれから負荷を学びました。Davidに感謝します。
マクナブ

@McNabうまくいったと聞いてうれしいです。間違いなく、Magentoのより複雑な領域の1つが対処されています。:)
デビダルガー

リンクされたブログの+1。最初に読んだ数回は見落としていました。それは大きな助けです。
pspahn

6

別のイベントがあります:sales_quote_item_set_productMage_Sales_Model_Quote_Item :: setProduct

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

このイベントを使用して、製品税クラスを変更できます。quoteItem getQtyメソッドを使用して、カートに追加されたqtyを見つけます。


このおかげで、知っておくと便利です。@ davidalgerの回答に基づいて、製品の税務クラスを変更するのではなく、見積モデルを変更する必要があることに気付きました。知っておくと良い。
マクナブ

さて、実際に見積品目税クラスを変更することができます。また、イベントでquoteItemオブジェクトにアクセスすることもできます。
PandaWebStudio

ああ、私は誤解しました。明確にしてくれてありがとう:)
McNab

@PandaWebStudio、見積品目のカスタム税額を設定する方法は?これが私の質問です。magento.stackexchange.com
questions / 274520 /

2

たぶん、税クラスを変更しようとするのは最良のアプローチではないかもしれません。より高い税率のクラスを使用する製品に同様の製品を作成し、その製品のカートに最小数量を設定してください。次に、checkout_cart_update_items_afterを使用して、カート内の合計数量に基づいて製品を交換しますか?

これは間違いなく「ベストプラクティス」ではありませんが、別の方向で考えるのに役立つ場合があります。

または、http://www.mageworx.com/multi-fees-magento-extension.htmlで何かを設定してみてください。追加の税金に対して「手数料」を追加します。これは実際にはより良い方法かもしれませんが、税の合計には表示されず、追加の注文合計行として表示されます。


サンダーに返信いただきありがとうございます。それは良い考えであり、私はそれを考えていませんでした。なぜ私がそれを気に入らないのかを説明します-基礎となる製品はすべてUnirgyのuMarketplaceスイートを介して実行されており、価格比較サイトとして実行されているようにそれを取得するタスクのモンスターでした。それは大きな仕事だと思う。この見積品目を更新できない場合は、見なければなりません。
マクナブ

くそー、私はこの賞金にすべての担当者を費やしたので、あなたの答えを支持することすらできません!+1 :)さらに取得すると、投票します。
マクナブ

ハハ問題ありません、私は問題を理解し、これはケースの良い解決策ではないでしょう。私は多人数で行くと思います。それは「よりクリーンな」ソリューションです
サンダー・マンジェル

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.