0

I am trying to use the new commerce_fee module to programmatically apply a fee during admin payment flow. I did a simple form_alter to the commerce_payment_add form to have a list of my Fee entities show up as checkboxes. This allows staff to add the specific fee if they choose.

I also set:

$form['payment']['amount']['#default_value']['number'] = $form['payment']['amount']['#default_value']['number'] + $form_state->getValues()['fee_amount'];

so that the fee is added in to the next step as the amount which will be charged to the customer's CC.

But the Fee is not properly added to my Order. I have seen Commerce documentation and a post here re: this but they do not work. At the moment I have a #submit added to the payment_add_form which follows some of the code I have seen; but no luck:

function _sia_add_fee_to_order (&$form, $form_state) {
  // its crazy that i need to figure out the Order from the URL; why isn't it in the form??
  $url = $_SERVER['REQUEST_URI'];
  $bits = explode('/', $url);
  $order_id = $bits[4];

  $order = Order::load($order_id);
  $fee = current(Drupal\commerce_fee\Entity\Fee::loadMultiple());

  $price = $fee->getPlugin()->getConfiguration()['amount'];
  $splitter = \Drupal::getContainer()->get('commerce_order.price_splitter');
  $amounts = $splitter->split($order, new Price($price['number'], $price['currency_code']));

  foreach ($order->getItems() as $order_item) {
    $order_item->addAdjustment(new Adjustment([
      'type' => 'fee',
      'label' => $fee->getName(),
      'amount' => $amounts[$order_item->id()],
      'source_id' => $fee->id(),
    ]));
  }

  $fee->apply($order);
  $order->recalculateTotalPrice();
  $order->save();
}

The post I saw here left out all the commerce documentation steps of adding adjustments to each line item and simply had the $fee->apply() function. Neither of theses work.

ADDED: More info about commerce_fee: https://www.drupal.org/project/commerce/issues/2903716, https://github.com/lisastreeter/commerce_fee

This is basically the commerce "promotion" module but redone to be more specific to fees. The question i have posted could be asked re: promotions as well; as should apply equally to either.

4
  • Could not find the commerce fee module that you speak of. Can you provide link?
    – No Sssweat
    Jul 9, 2020 at 22:07
  • Added info/links to original post. Basically it is the same as "promotion" module; but for fees. The same same question could be asked of how to add a promotion and it would likely apply the same to my question.
    – liquidcms
    Jul 10, 2020 at 17:43
  • try using the service instead, $fee = \Drupal::service('commerce_fee.fee_order_processor');
    – No Sssweat
    Jul 11, 2020 at 8:48
  • Not sure how that would be used. I see that service has a method called process; which requires an OrderInterface rather than an order Entity, so i added this: $processor = \Drupal::service('commerce_fee.fee_order_processor'); $orderInterface = OrderInterface::load($order->id()); $result = $processor->process($orderInterface); and i get this error: Cannot call abstract method Drupal\Core\Entity\EntityInterface::load()
    – liquidcms
    Jul 13, 2020 at 15:46

1 Answer 1

0

After a lot of trial and error I thought of moving the code out of the form submit function and into an event subscription; in particular, i moved it to the commerce_order.order.paid event.

So I ended up with this in an existing event subscriber call back I already had:

  public function placeOrder($event) {
    $order = $event->getOrder();

    $fee = current(\Drupal\commerce_fee\Entity\Fee::loadMultiple());
    $price = $fee->getPlugin()->getConfiguration()['amount'];
    $splitter = \Drupal::getContainer()->get('commerce_order.price_splitter');
    $amounts = $splitter->split($order, new Price($price['number'], $price['currency_code']));
    foreach ($order->getItems() as $order_item) {
      $adjustments = $order_item->getAdjustments();
      $adjustments[] = new Adjustment([
        'type' => 'fee',
        'label' => $fee->getName(),
        'amount' => $amounts[$order_item->id()],
        'source_id' => $fee->id(),
      ]);
      $order_item->setAdjustments($adjustments);
      $order_item->save();
    }
  }

This code includes code to split the fee up among all the items; which may or may not be what you want (although doesn't seem like it could ever be a bad idea).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.