You are here

protected function InvoiceGenerator::doGenerate in Commerce Invoice 8.2

See also

\Drupal\commerce_invoice\InvoiceGeneratorInterface::generate()

1 call to InvoiceGenerator::doGenerate()
InvoiceGenerator::generate in src/InvoiceGenerator.php
Generates an invoice for the given orders.

File

src/InvoiceGenerator.php, line 84

Class

InvoiceGenerator

Namespace

Drupal\commerce_invoice

Code

protected function doGenerate(array $orders, StoreInterface $store, ProfileInterface $profile = NULL, array $values = [], $save = TRUE) {
  $invoice_storage = $this->entityTypeManager
    ->getStorage('commerce_invoice');
  $values += [
    'store_id' => $store
      ->id(),
    'billing_profile' => $profile,
  ];

  // If we're not generating an invoice for a single order, don't inherit its
  // customer information and payment method.
  if (count($orders) !== 1) {
    $values += [
      'mail' => NULL,
      'uid' => NULL,
      'payment_method' => NULL,
    ];
  }

  // Assume the order type from the first passed order, we'll use it
  // to determine the invoice type to create.

  /** @var \Drupal\commerce_order\Entity\OrderInterface $first_order */
  $first_order = reset($orders);

  /** @var \Drupal\commerce_invoice\Entity\InvoiceInterface $invoice */
  $invoice = $invoice_storage
    ->createFromOrder($first_order, $values);

  // Find any (partial) invoices that reference the given orders so we can
  // subtract their adjustments and invoice items quantities and adjustments.
  $existing_invoices = $invoice_storage
    ->loadByOrders($invoice
    ->bundle(), $orders);
  $total_paid = NULL;

  /** @var \Drupal\commerce_order\Entity\OrderInterface[] $orders */
  foreach ($orders as $order) {
    $existing_invoices_for_order = array_filter($existing_invoices, function (InvoiceInterface $invoice) use ($order) {
      $order_ids = array_column($invoice
        ->get('orders')
        ->getValue(), 'target_id');
      return in_array($order
        ->id(), $order_ids);
    });

    // Copy over all the adjustments from the order, if there any left after
    // taking into account those that were applied to previous invoices.
    foreach ($this
      ->getAdjustmentsFromEntity($order, $existing_invoices_for_order) as $adjustment) {
      $invoice
        ->addAdjustment($adjustment);
    }
    foreach ($this
      ->getInvoiceItemsFromOrder($order, $invoice, $existing_invoices_for_order) as $invoice_item) {
      if ($save) {
        $invoice_item
          ->save();
      }
      $invoice
        ->addItem($invoice_item);
    }
    $total_paid = $total_paid ? $total_paid
      ->add($order
      ->getTotalPaid()) : $order
      ->getTotalPaid();
  }
  if ($total_paid) {
    $invoice
      ->setTotalPaid($total_paid);
  }
  $invoice
    ->setOrders($orders);
  if ($invoice
    ->getState()
    ->getId() === 'draft') {
    $invoice
      ->getState()
      ->applyTransitionById('confirm');
  }
  if ($save) {
    $invoice
      ->save();
  }
  return $invoice;
}