You are here

protected function RecurringOrderManager::applyCharges in Commerce Recurring Framework 8

Applies subscription charges to the given recurring order.

Note: The order items are not saved.

Parameters

\Drupal\commerce_order\Entity\OrderInterface $order: The recurring order.

\Drupal\commerce_recurring\Entity\SubscriptionInterface $subscription: The subscription.

\Drupal\commerce_recurring\BillingPeriod $billing_period: The billing period.

4 calls to RecurringOrderManager::applyCharges()
RecurringOrderManager::refreshOrder in src/RecurringOrderManager.php
Refreshes the given recurring order.
RecurringOrderManager::renewOrder in src/RecurringOrderManager.php
Renews the given recurring order.
RecurringOrderManager::startRecurring in src/RecurringOrderManager.php
Starts the recurring process for the given subscription.
RecurringOrderManager::startTrial in src/RecurringOrderManager.php
Starts the trial for the given subscription.

File

src/RecurringOrderManager.php, line 274

Class

RecurringOrderManager
Provides the default recurring order manager.

Namespace

Drupal\commerce_recurring

Code

protected function applyCharges(OrderInterface $order, SubscriptionInterface $subscription, BillingPeriod $billing_period) {

  /** @var \Drupal\commerce_order\OrderItemStorageInterface $order_item_storage */
  $order_item_storage = $this->entityTypeManager
    ->getStorage('commerce_order_item');
  $existing_order_items = [];
  foreach ($order
    ->getItems() as $order_item) {
    if ($order_item
      ->get('subscription')->target_id == $subscription
      ->id()) {
      $existing_order_items[] = $order_item;
    }
  }
  if ($subscription
    ->getState()
    ->getId() == 'trial') {
    $charges = $subscription
      ->getType()
      ->collectTrialCharges($subscription, $billing_period);
  }
  else {
    $charges = $subscription
      ->getType()
      ->collectCharges($subscription, $billing_period);
  }
  $order_items = [];
  foreach ($charges as $charge) {
    $order_item = array_shift($existing_order_items);
    if (!$order_item) {

      /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
      $order_item = $order_item_storage
        ->create([
        'type' => $this
          ->getOrderItemTypeId($subscription),
        'order_id' => $order
          ->id(),
        'subscription' => $subscription
          ->id(),
      ]);
    }

    // @todo Add a purchased_entity setter to OrderItemInterface.
    $order_item
      ->set('purchased_entity', $charge
      ->getPurchasedEntity());
    $order_item
      ->setTitle($charge
      ->getTitle());
    $order_item
      ->setQuantity($charge
      ->getQuantity());
    $order_item
      ->set('billing_period', $charge
      ->getBillingPeriod());

    // Populate the initial unit price, then prorate it.
    $order_item
      ->setUnitPrice($charge
      ->getUnitPrice());
    if ($charge
      ->needsProration()) {
      $prorater = $subscription
        ->getBillingSchedule()
        ->getProrater();
      $prorated_unit_price = $prorater
        ->prorateOrderItem($order_item, $charge
        ->getBillingPeriod(), $charge
        ->getFullBillingPeriod());
      $order_item
        ->setUnitPrice($prorated_unit_price, TRUE);
    }

    // Avoid setting unsaved order items for now, to avoid #3017259.
    if ($order_item
      ->isNew()) {
      $order_item
        ->save();
    }
    $order_items[] = $order_item;
  }
  $order
    ->setItems($order_items);

  // Delete any previous leftover order items.
  if ($existing_order_items) {
    $order_item_storage
      ->delete($existing_order_items);
  }
}