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 '20 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 '20 at 17:43
  • try using the service instead, $fee = \Drupal::service('commerce_fee.fee_order_processor'); – No Sssweat Jul 11 '20 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 '20 at 15:46
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, privacy policy and cookie policy

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