You are here

private function InvoiceGenerator::getInvoiceItemsFromOrder in Commerce Invoice 8.2

Return an array of invoice items from a given order.

Parameters

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

\Drupal\commerce_invoice\Entity\InvoiceInterface $invoice: An invoice.

\Drupal\commerce_invoice\Entity\InvoiceInterface[] $existing_invoices: (optional) An array of existing (partial) invoices for this order. Defaults to an empty array.

Return value

\Drupal\commerce_invoice\Entity\InvoiceItemInterface[] An array of invoice items.

1 call to InvoiceGenerator::getInvoiceItemsFromOrder()
InvoiceGenerator::doGenerate in src/InvoiceGenerator.php

File

src/InvoiceGenerator.php, line 200

Class

InvoiceGenerator

Namespace

Drupal\commerce_invoice

Code

private function getInvoiceItemsFromOrder(OrderInterface $order, InvoiceInterface $invoice, array $existing_invoices = []) {
  $invoice_items = [];

  // Get the default invoice language so we can set it on invoice items.
  $default_langcode = $invoice
    ->language()
    ->getId();
  $invoice_item_storage = $this->entityTypeManager
    ->getStorage('commerce_invoice_item');
  foreach ($order
    ->getItems() as $order_item) {

    /** @var \Drupal\commerce_order\Entity\OrderItemTypeInterface $order_item_type */
    $order_item_type = OrderItemType::load($order_item
      ->bundle());
    $invoice_item_type = $order_item_type
      ->getPurchasableEntityTypeId() ?: 'default';

    /** @var \Drupal\commerce_invoice\Entity\InvoiceItemInterface $invoice_item */
    $invoice_item = $invoice_item_storage
      ->create([
      'langcode' => $default_langcode,
      'type' => $invoice_item_type,
    ]);
    $invoice_item
      ->populateFromOrderItem($order_item);

    // Look through all the existing invoices for this order and subtract the
    // quantity of their matching invoice items. We don't need to this for
    // each invoice item translation below because
    // InvoiceItem::populateFromOrderItem() only sets the quantity value on
    // the default translation.
    foreach ($existing_invoices as $existing_invoice) {
      foreach ($existing_invoice
        ->getItems() as $previous_invoice_item) {
        if ($invoice_item
          ->getOrderItemId() == $previous_invoice_item
          ->getOrderItemId()) {
          $new_quantity = Calculator::subtract($invoice_item
            ->getQuantity(), $previous_invoice_item
            ->getQuantity());
          $invoice_item
            ->setQuantity($new_quantity);
        }
      }
    }

    // Ensure that order items that have corresponding quantity value in the
    // existing (partial) invoices can not be added to a new invoice.
    if (Calculator::compare($invoice_item
      ->getQuantity(), '0') == 0) {
      continue;
    }

    // Look through all the existing invoices for this order and subtract the
    // adjustments of their matching invoice items.
    $previous_invoice_items = [];
    foreach ($existing_invoices as $existing_invoice) {
      $previous_invoice_items = array_merge($previous_invoice_items, array_filter($existing_invoice
        ->getItems(), function ($previous_invoice_item) use ($invoice_item) {
        return $invoice_item
          ->getOrderItemId() == $previous_invoice_item
          ->getOrderItemId();
      }));
    }
    $invoice_item
      ->setAdjustments($this
      ->getAdjustmentsFromEntity($order_item, $previous_invoice_items));

    // If the invoice is translated, we need to generate translations in
    // all languages for each invoice item.
    foreach ($invoice
      ->getTranslationLanguages(FALSE) as $langcode => $language) {
      $translated_invoice_item = $invoice_item
        ->addTranslation($langcode);

      // We're calling InvoiceItem::populateFromOrderItem() for each
      // translation since that logic is responsible for pulling the
      // translated variation title, if available.
      $translated_invoice_item
        ->populateFromOrderItem($order_item);
    }
    $invoice_items[] = $invoice_item;
  }
  return $invoice_items;
}