code: private function feedShipmentInvoice(Invoice\InvoiceInterface $invoice)
      {
          $changed = false;
  
          $shipment = $invoice->getShipment();
  
          $calculator = $this->invoiceBuilder->getInvoiceCalculator();
  
          // Add expected good lines
          /** @var Invoice\InvoiceLineInterface $line */
          foreach ($shipment->getItems() as $shipmentItem) {
              $saleItem = $shipmentItem->getSaleItem();
  
              $max = $shipment->isReturn()
                  ? $calculator->calculateCreditableQuantity($saleItem)
                  : $calculator->calculateInvoiceableQuantity($saleItem);
  
              if (0 < $quantity = min($max, $shipmentItem->getQuantity())) {
                  $line = $this->invoiceBuilder->findOrCreateGoodLine($invoice, $saleItem, $max);
                  if ($line->getQuantity() !== $quantity) {
                      $line->setQuantity($quantity);
                      $changed = true;
                  }
              } /*else {
                  // TODO find and remove line ?
                  $invoice->removeLine($line);
                  $changed = true;
              }*/
          }
  
          if ($invoice->hasLineByType(Document\DocumentLineTypes::TYPE_GOOD)) {
              // Add expected discount lines
              $sale = $invoice->getSale();
              foreach ($sale->getAdjustments(Common\AdjustmentTypes::TYPE_DISCOUNT) as $saleAdjustment) {
                  foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_DISCOUNT) as $line) {
                      if ($saleAdjustment === $line->getSaleAdjustment()) {
                          continue 2; // Invoice line found -> next sale adjustment
                      }
                  }
  
                  // Invoice line not found -> create it
                  $this->invoiceBuilder->buildDiscountLine($saleAdjustment, $invoice);
  
                  $changed = true;
              }
  
              // Add expected shipment line
              if (null !== $sale->getShipmentMethod() && !$this->isShipmentAmountInvoiced($invoice)) {
                  $this->invoiceBuilder->buildShipmentLine($invoice);
              }
          }
  
          return $changed;
      }
docs: Creates invoice expected lines regarding to his associated shipment.
  
  @param Invoice\InvoiceInterface $invoice
  
  @return bool Whether the invoice has been changed