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?