Score:0

Adjust total price in commerce checkout

in flag

I have a store setup with 2 products. Public and private tours. Public tours are 10 for each unit.

Private tours on the other hand are only meant to collect a deposit. I need the total to be $50 no matter the quantity selected and the rest is paid on site.

I tried creating a custom PromotionOffer as seen below. I can create the promotion but it doesn't seem to apply while in the cart/checkout. I even tried making it a coupon and when I apply the coupon it says its not valid, may have expired or been used. I have one condition set and that is they have a private tour in their cart.

<?php

namespace Drupal\tour_reservation\Plugin\Commerce\PromotionOffer;

use Drupal\commerce_order\Adjustment;
use Drupal\commerce_price\Price;
use Drupal\commerce_promotion\Entity\PromotionInterface;
use Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\PromotionOfferBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Discounts a cart to a fixed amount.
 *
 * @CommercePromotionOffer(
 *   id = "tour_reservation_discount_to_fixed",
 *   label = @Translation("Sets cart total to a fixed amount"),
 *   entity_type = "commerce_order_item",
 * )
 */
class OrderFixedPrice extends PromotionOfferBase {

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'amount' => NULL,
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form += parent::buildConfigurationForm($form, $form_state);

    $amount = $this->configuration['amount'];
    // A bug in the plugin_select form element causes $amount to be incomplete.
    if (isset($amount) && !isset($amount['number'], $amount['currency_code'])) {
      $amount = NULL;
    }

    $form['amount'] = [
      '#type' => 'commerce_price',
      '#title' => $this->t('Amount'),
      '#default_value' => $amount,
      '#required' => TRUE,
      '#description' => $this->t('Set cart price. Format: 9.99'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValue($form['#parents']);
    if ($values['amount']['number'] < 0) {
      $form_state->setError($form, $this->t('Amount cannot be negative.'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);

    $values = $form_state->getValue($form['#parents']);
    $this->configuration['amount'] = $values['amount'];
  }

  /**
   * {@inheritdoc}
   */
  public function apply(EntityInterface $entity, PromotionInterface $promotion) {
    $this->assertEntity($entity);
    /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
    $order_item = $entity;
    $target_amount = $this->getAmount();
    $order_item->addAdjustment(new Adjustment([
      'type' => 'promotion',
      'label' => t('Discount'),
      'amount' => $target_amount,
      'source_id' => $promotion->id(),
    ]));
  }

  /**
   * Gets the offer amount.
   *
   * @return \Drupal\commerce_price\Price|null
   *   The amount, or NULL if unknown.
   */
  protected function getAmount() {
    if (!empty($this->configuration['amount'])) {
      $amount = $this->configuration['amount'];
      return new Price($amount['number'], $amount['currency_code']);
    }
  }

}

Ideally, I dont want to use promotions and rather just adjust the price in the cart. Any ideas?

cn flag
Are these different product types? I would make two product types, public that has whatever the price is and private that is free. Then add some logic to make sure you don't have both types in the cart at once. Then add the deposit as a "shipping" fee for private products.
in flag
That could work as well. I think I am going to just limit the quantity of private tours to 1 but still save the number of guests. I used this solution https://drupal.stackexchange.com/a/271556/26823
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.