Commerce-Kaufabwicklung - Aktualisieren Sie den Warenkorb, nachdem der Benutzer eine Versandoption ausgewählt hat (Ajax).

7

Ich arbeite an einer einseitigen Kaufabwicklung und versuche, den Warenkorb-Überprüfungsbereich mit einem Versandpreis zu aktualisieren, während der Benutzer eine Versandoption auswählt .

Ich habe den Versandoptionen #ajax-Informationen beigefügt, um das Warenkorb-Überprüfungsformular zu aktualisieren, wenn eine Versandoption gespeichert wird.

Ändern des Ajax-Rückrufs für den Handelsversand an der Kasse

if($form_id == 'commerce_checkout_form_checkout') {
  $form['commerce_shipping']['shipping_service']['#ajax']['callback'] = 'mshop_shipping_pane_service_details_refresh';
}

Ajax-Rückruf

function mshop_shipping_pane_service_details_refresh($form, $form_state) {
  // Update shipping form
  $commands[] = ajax_command_replace('#' . $form['commerce_shipping']['service_details']['#id'], render($form['commerce_shipping']['service_details']));

  // Update checkout cart review
  list($view_id, $display_id) = explode('|', variable_get('commerce_cart_contents_pane_view', 'commerce_cart_summary|default'));
  $commands[] = ajax_command_replace('.view-mshop-cart-shopping-cart-summary', commerce_embed_view($view_id, $display_id, array(arg(1))));

  return array('#type' => 'ajax', '#commands' => $commands);
}

Das Problem: Der AJAX funktioniert, die aktualisierte Ansicht zur Überprüfung des Warenkorbs wird aktualisiert, aber die Versandoption wird nicht angewendet.

Ich vermute, dass die Bestellung nicht gespeichert wird, da das Formular nur aktualisiert und nicht gesendet wird. Da die Ansicht der Warenkorbbewertung auf der Bestellung basiert und die Versandoption noch nicht in der Bestellung gespeichert ist, werden in der Warenkorbbewertung nicht die richtigen Versandinformationen angezeigt.

Irgendeine Problemumgehung?

BEARBEITEN:

Dank milchowsky Kommentar konnte ich die Bestellung mit der auf die Bestellung angewendeten Versandrate speichern. Anschließend wird die Ansicht zur Überprüfung des Warenkorbs korrekt angezeigt, wobei die aktualisierte Warenkorbrate angewendet wird.

/**
 * Ajax callback: Returns the shipping details form elements that match the
 * currently selected shipping service.
 */
function mshop_shipping_pane_service_details_refresh($form, &$form_state, $checkout_pane, $order) {

  // Get order from form
  list($order, $checkout_pane) = $form_state['build_info']['args'];

  // Load up to date order
  $order = commerce_order_load($order->order_id);

  // Get selected 
  $service_name = $form['commerce_shipping']['shipping_service']['#default_value'];

  commerce_shipping_service_rate_order($service_name, $order);

  // Delete any existing shipping line items from the order.
  commerce_shipping_delete_shipping_line_items($order, TRUE);

  // Extract the unit price from the calculated rate.
  $rate_line_item = $order->shipping_rates[$service_name];
  $rate_line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $rate_line_item);
  $unit_price = $rate_line_item_wrapper->commerce_unit_price->value();

  // Create a new shipping line item with the calculated rate from the form.
  $line_item = commerce_shipping_line_item_new($service_name, $unit_price, $order->order_id, $rate_line_item->data, $rate_line_item->type);

  // Save and add the line item to the order.
  $new_line_item = commerce_shipping_add_shipping_line_item($line_item, $order, TRUE);
  commerce_order_save($order);


  // Update shipping form
  $commands[] = ajax_command_replace('#' . $form['commerce_shipping']['service_details']['#id'], render($form['commerce_shipping']['service_details']));


  // Update checkout cart review
  list($view_id, $display_id) = explode('|', variable_get('commerce_cart_contents_pane_view', 'commerce_cart_summary|default'));
  $commands[] = ajax_command_replace('.view-mshop-cart-shopping-cart-summary', commerce_embed_view($view_id, $display_id, array($order->order_id)));

  $commands[] = ajax_command_after('.main form', theme('status_messages'));

  // $commands[] = ajax_command_after('.'.$form['#attributes']['class'][1].':eq(0)',theme('status_messages'));
  return array('#type' => 'ajax', '#commands' => $commands);
}
E. de Saint Chamas
quelle
Überprüfen Sie, ob Sie vorhandenen Rückruf nicht überschreiben, indem Sie$form['commerce_shipping']['shipping_service']['#ajax']['callback'] = ...
milchowski
Ich kann es nicht zum Laufen bringen - ist der Code if($form_id == 'commerce_checkout_form_checkout') { $form['commerce_shipping']['shipping_service']['#ajax']['callback'] = 'mshop_shipping_pane_service_details_refresh'; } implementiert hook_form_alteroder ein spezieller Commerce-Hook?
Dalmaz
Ja, ich implementiere einen grundlegenden hook_form_alter (). Meiner Seite nach funktioniert es mit der neuesten Version von Drupal Commerce. Wird Ihr Rückruf ausgeführt?
E. de Saint Chamas

Antworten:

4

Du hast recht. Die Versandkosten werden erst angewendet, nachdem Sie das Formular gesendet haben (Klicken Sie auf "Weiter").

Beim Absenden gelten alle Ihre Versandregeln (oder Flatrates) und die Bestellung wird mit neuen Werbebuchungen gespeichert (der Versand erfolgt über einen benutzerdefinierten Werbebuchungstyp).

Die Berechnung wird in der Datei trade_shipping_pane_checkout_form_submit () ausgeführt.

Sie können also versuchen, diese Funktion (oder einige Teile davon) im Ajax-Rückruf auszuführen, bevor der Warenkorb aktualisiert wird.

Hier ist ein Beispiel für die Anwendung von Versandkosten, wenn Sie das Flatrate-Modul verwenden: Hinzufügen von Versand zur programmgesteuerten Bestellung über das Modul .

melkowski
quelle
1
Danke, Ihre zweite Lösung funktioniert wie ein Zauber. Ich habe Ihre erste Lösung bevorzugt, bei der die Bestellung während des Bestellvorgangs nicht geladen und gespeichert werden musste, die Commerce_shipping_pane_checkout_form_submit () jedoch nicht korrekt implementiert werden konnte, da zwei Variablen erforderlich sind, auf die ich in dieser Funktion nicht zugreifen kann. Ich werde meinen Beitrag mit der Lösung aktualisieren.
E. de Saint Chamas
1
Epische Antwort und bearbeiten! Thx
Michiel
Gibt es eine Möglichkeit, dies über die Benutzeroberfläche zu erzwingen?
Nizz0k
2

Zunächst einmal vielen Dank, dass Sie diese Lösung veröffentlicht haben!

Ich habe diesen 500-Fehler von der AJAX-Antwort erhalten: "EntityMetadataWrapperException: Fehlende Datenwerte. In EntityMetadataWrapper-> value ().

Ich wollte kostenlosen Versand für Bestellungen über 100 US-Dollar anbieten und aktivierte daher das Modul trade_order_total ( https://www.drupal.org/sandbox/joshmiller/2718047 ), das den Fehler bei der Auswahl einer Versandmethode hervorhob.

Nach einigem Debuggen stellte ich fest, dass es nur auftrat, wenn die Zeile trade_order_save () enthalten war.

Da ich festgelegt habe, dass meine Checkout-Bereiche alle auf derselben Seite angezeigt werden und mein Überprüfungsbereich deaktiviert ist, habe ich diese Zeile in eine IF-Anweisung eingeschlossen:

//get checkout panes
$panes = commerce_checkout_panes();

//check if the Review pane is enabled
if ($panes['checkout_review']['enabled']){
  //review is enabled
  commerce_order_save($order);
}

Kommentare / Verbesserungen sind erwünscht!

Muss beeindrucken
quelle